一文带你了解Jwt和session的区别

全栈开发



前言

因为要重构公司的web端产品,和前端一起对了下接口。在对接用户登录的时候,发现当用户关掉浏览器后再次打开浏览器竟然不能无密码登录。然后就和前端商量了下,后端采用jwt技术将生成token给前端,前端将token存储到localstorage,以便后续请求以token方式进行无秘登录以及权限校验。
但是今天在该代码的时候发现后端有用到session进行用户登录的一个校验,似乎和我用的jwt实现的效果有异曲同工之妙,我就好奇了这个和jwt到底有什么区别呢?然后就进行了一番研究…


Session和Jwt是什么?

Session 和 JWT(JSON Web Token) 是两种用于用户身份验证和会话管理的技术,它们各自有不同的特点和应用场景。

Session

概念

Session 是一种服务器端的会话管理技术,用于在用户和服务器之间保持状态信息。Session 通常通过在服务器端存储会话数据来实现。

工作场景

  • 配置

安装需要的库(使用redis作为存储库)。

npm install express-session connect-redis redis

在express中的配置:

const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redisClient = require('redis').createClient();

const app = express();
// 配置 session 中间件
const session_config = {
  store: new RedisStore({ client: redisClient }),
  secret: 'your_secret_key', // 用于加密 session ID 的密钥
  resave: false,             // 是否在每次请求时强制重新保存 session
  saveUninitialized: true,   // 是否在保存 session 前将其初始化
  cookie: { 
    secure: false, // 在 HTTPS 下设置为 true
    maxAge: 3600000 // Cookie 的过期时间(1 小时)
  }
}
app.use(session(session_config));

这样,我们就可以开始在express中使用session了。

  • 用户登录:
    用户提供凭据(如用户名和密码)进行登录。
    服务器验证凭据后,生成一个唯一的 Session ID,并将其存储在服务器端的会话存储中(如内存、文件、数据库或 Redis)。
// 示例路由:用户登录
app.post('/login', (req, res) => {
  const { userId, passWord } = req.body;

  // 在成功登录后存储用户 ID 到会话
  req.session.userId = userId;

  res.send('User logged in');
});

这样我们就把userId作为用户的唯一Session存到redis中了。

  • 发送 Session ID:
    服务器将 Session ID 通过 Set-Cookie 头发送到客户端。浏览器会将这个 Session ID 存储在 Cookie 中。这一步不用我们去做,当我们配置好了中间件express会自动帮我们将 Set-Cookie 头发送到客户端,就是这段代码:
app.use(session(session_config));
  • 后续请求:
    用户在后续的请求中,浏览器会自动将存储的 Session ID Cookie 发送到服务器。服务器使用 Session ID 查找和检索对应的会话数据,以识别用户并处理请求。比如当我们获取用户信息的时候,我们就可以用浏览器发过来的Session ID Cookie找到对应的Session id的数据,进而取出该Session id的在登录时存储的userId,即req.session.userId
// 示例路由:获取用户信息
app.get('/user-info', (req, res) => {
  if (req.session.userId) {
    res.send(`Logged in as user: ${req.session.userId}`);
  } else {
    res.send('No user logged in');
  }
});
  • 关掉浏览器再次打开浏览器无密码登录

上述用户进行登录后,服务器将 Session ID 通过 Set-Cookie 头发送到客户端,用户登录后即使关闭浏览器并重新打开,Cookie 会在客户端保存,保持会话状态。所以当用户再次访问时,浏览器会自动发送保存的 Cookie,服务器能够识别用户并恢复会话。

  • 会话管理:
    服务器可以根据需要更新或销毁会话数据。例如,用户登出时可以删除对应的 Session 数据。
// 示例路由:用户登出
app.post('/logout', (req, res) => {
  req.session.destroy(err => {
    if (err) {
      return res.status(500).send('Failed to destroy session');
    }
    res.send('User logged out');
  });
});

Jwt

概念

JWT 是一种无状态的身份验证机制,它使用 JSON 对象表示的 Token 来进行用户认证和信息交换。JWT 通常用于在客户端和服务器之间安全地传输信息。

工作场景

  • 配置
npm install express  jsonwebtoken
  • 用户登录:

首先用户提供凭据进行登录。服务器验证凭据后,生成一个 JWT。JWT通常包含用户的信息(通常是用户 ID 和其他自定义数据)和签名,用于验证 Token 的完整性,然后返回给前端,前端拿到这个Token并存到localStorage,这样就可以将Token持久化存在浏览器里。

const express = require('express');
const jwt = require('jsonwebtoken');

const app = express();
const secretKey = 'your_secret_key';

app.use(express.json());

app.post('/api/login', (req, res) => {
    const { username, password } = req.body;

    if (username === 'user' && password === 'password') {
        const authToken = jwt.sign({ username }, secretKey, { expiresIn: '1h' });
        res.json({ token: authToken });
    } else {
        res.status(401).json({ message: 'Invalid credentials' });
    }
});
  • 发送 JWT:

服务器将 JWT 发送给客户端,客户端可以将 JWT 存储在 Cookie、localStorage 或 sessionStorage 中。(跟上面最后有点重复)

  • 后续请求:
    用户在后续的请求中,将 JWT 通过请求头(如 Authorization: Bearer )发送到服务器。
    服务器验证 JWT 的签名和有效性,从中提取用户信息,并处理请求。

前端:

const axios = require('axios');

axios.post('/some-protected-route', {}, {
  headers: {
    Authorization: `Bearer ${yourJwtToken}`,
  },
});

后端:

const jwt = require('jsonwebtoken');

// 中间件验证 JWT
const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // 提取 Bearer Token

  if (token == null) return res.sendStatus(401); // 如果没有 token,返回 401

  jwt.verify(token, 'your_jwt_secret_key', (err, user) => {
    if (err) return res.sendStatus(403); // 如果 token 无效,返回 403
    req.user = user; // 将解码后的用户信息存储在 req 对象中
    next(); // 继续处理请求
  });
};

// 使用中间件
app.use('/some-protected-route', authenticateToken, (req, res) => {
  // 处理受保护的路由
  res.json({ message: 'Access granted', user: req.user });
});
  • 关掉浏览器再次打开浏览器无密码登录
// app.js
import axios from 'axios';
import './axiosConfig'; // 引入配置好的 Axios 拦截器

const checkAuthToken = () => {
  // 从 localStorage 中获取 JWT
  const token = localStorage.getItem('authToken');
  
  if (token) {
    // 如果 JWT 存在,设置 Axios 默认请求头
    axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;

    // 可选:可以发送请求来验证 token 是否仍然有效
    // axios.get('/verify-token')
    //   .then(response => {
    //     // Token 仍然有效,继续执行
    //   })
    //   .catch(error => {
    //     // Token 无效或请求失败,处理逻辑(如清除 token 并引导用户登录)
    //     console.error('Token verification failed', error);
    //     localStorage.removeItem('authToken');
    //     // 可能需要引导用户登录
    //   });
  } else {
    // 如果 JWT 不存在,引导用户登录或显示登录界面
    console.log('No auth token found. Redirecting to login...');
    // 例如,重定向到登录页面
    window.location.href = '/login';
  }
};

// 页面加载时检查 JWT
document.addEventListener('DOMContentLoaded', () => {
  checkAuthToken();
});

  • 无状态:

由于 JWT 是自包含的,服务器不需要存储会话状态,所有必要的信息都包含在 JWT 中。

总结

session

  • 存储位置: 服务器端。

  • 机制: 服务器生成和管理会话 ID,客户端通过 Cookie 发送 Session ID。

  • 优点:
    1.集中管理: Session 数据存储在服务器端,减少了客户端存储的复杂性;
    2.安全性: 由于敏感数据(如用户信息)存储在服务器上,相比于存储在客户端,通常更安全;
    3.易于实现: 很多后端框架和库都原生支持 session,简化了实现过程;
    4.过期管理: Session 过期由服务器控制,不需要客户端进行处理;

  • 缺点:
    1.存储负担: 每个用户的 session 数据都存储在服务器端,可能会消耗大量的服务器内存和存储资源。
    2.跨域问题: 依赖于浏览器的 Cookie 机制,这可能会引发跨域问题,尤其是在多个子域名或不同的应用之间。
    3.负载均衡: 在分布式系统中,多个服务器处理同一应用时,Session 数据的同步和管理可能变得复杂。需要使用外部存储(如 Redis)来解决这个问题。

jwt

  • 存储位置: 客户端。
  • 机制: 服务器生成自包含的 Token,客户端通过请求头发送 Token。
  • 优点:
    1.减少服务器负担: Token 数据存储在客户端,减少了服务器的存储需求。
    2.灵活性: 用户可以在多个设备上使用 Token。
    3.扩展性: Token 机制是无状态的,服务器不需要存储 session 数据,适合分布式系统和微服务架构。
    跨域支持:
    4.方便: Token 不依赖于 Cookie,支持在不同的子域名和跨域场景中使用。
    5.简化认证:无状态认证: 认证信息包含在 Token 中,简化了每次请求的认证流程。
  • 缺点:
    1.安全性问题:客户端存储: 存储在客户端,可能被盗取或篡改。需要额外的措施(如 HTTPS、Token 加密)来保护 Token。
    2.无法失效: Token 一旦生成,在有效期内都有效,无法像 Session 那样容易地失效或撤销。需要实现刷新 Token 机制来处理 Token 过期问题。
    3.复杂性:需要处理 Token 的生成、存储、过期和刷新,可能比 Session 实现要复杂。
    4.数据量大: JWT 可以包含很多信息,可能导致 Token 变得较大,影响性能(特别是在请求头中传递时)。

选择 Session 还是 JWT 取决于具体的应用需求和架构设计。在需要集中管理会话状态的传统应用中,Session 可能是更好的选择;而在分布式系统或微服务架构中,JWT 可能更适合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hola173841439

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值