会话身份验证 vs 令牌身份验证:孰优孰劣?

2024年 4月 29日 80.5k 0

在本文中,我们将了解后端应用程序中使用的基于会话和令牌的身份验证方法。

基于会话的身份验证

简单讲,基于会话(Session)的身份验证使用存储在设备上的特殊代码(Session ID)来记住你访问网站时的身份,保持登录状态并记住你的信息,直到你离开或注销。

还没明白吗?别着急,我们一步一步来看。

1. 用户登录:

用户通过特殊请求通过邮箱和密码发送到服务器来登录。

2. 检查详情:

服务器检查提供的详细信息是否与为用户存储的信息匹配。

3. 创建会话:

如果一切正确,服务器将创建一个保存用户信息(如User ID、权限和时间限制)的“Session”。此信息安全地保存在服务器的存储中,名字可以使用诸如express-session。

4. 获取会话ID:

服务器将此“会话 ID”发送回用户的设备,通常作为响应中的Cookie。

5. 使用会话 ID:

每当用户想要从服务器获取某些内容时,他们的设备会自动在其请求中包含此会话 ID。

6. 服务器检查:

服务器使用此会话 ID 来查找会话存储中存储的有关会话用户的信息。

以下是express-session工作原理:

  • 当用户登录时,服务器会为该用户创建一个会话,并在包含会话 ID 的响应中设置一个 cookie🍪。

  • 浏览器会自动在向服务器发出的后续请求中包含此会话 ID cookie🍪。

  • 当服务器收到请求时,express-session 中间件使用 cookie🍪 中的会话 ID 来检索相关会话数据。

  • 存储在req.session中的数据(例如 userId)可用于处理请求。

7. 授予访问权限:

如果一切全都匹配,服务器就知道用户是真实的,并响应他们所请求的内容。

代码例子

下面是一个使用 Express.js 实现会话身份验证的 Node.js 应用程序的示例。

const express = require('express');const session = require('express-session');const app = express();// 中间件设置app.use(session({  secret: 'your_secret_key',  resave: false,  saveUninitialized: false,  cookie: {    httpOnly: true, // Set the cookie as HTTP-only, Optional    maxAge: 60*30 // In secs, Optional  }}));//登录app.post('/login', (req, res) => {  const { username, password } = req.body;  const user = users.find(u => u.username === username && u.password === password);  if (user) {    req.session.userId = user.id; // Store user ID in session    res.send('Login successful');  } else {    res.status(401).send('Invalid credentials');  }});//受保护页面app.get('/home', (req, res) => {  if (req.session.userId) {    // User is authenticated    res.send(`欢迎您光临,${req.session.userId}!`);  } else {    // User is not authenticated    res.status(401).send('Unauthorized');  }});//登出app.get('/logout', (req, res) => {  req.session.destroy(err => {    if (err) {      res.status(500).send('退出登录出现错误');    } else {      res.redirect('/'); // Redirect to the home page after logout    }  });});

基于令牌的身份验证

JWT 身份验证使用包含用户信息的数字签名令牌(Token),其允许对网站或应用程序进行安全且经过验证的访问,而无需重复登录。

让我们看一下基于令牌的身份验证的分步工作流程。

  • 用户登录请求:

  • 用户通过特定请求将电子邮件和密码发送到服务器来登录。

    2. 凭证验证:

    服务器根据存储的用户数据验证提供的凭据。

    3. 代币生成:

    验证成功后,服务器会创建一个令牌(通常为 JWT - JSON Web 令牌)。该令牌保存用户信息(声明),例如 user_id、权限。

    4. 令牌签名与哈希:

    该令牌使用密钥进行签名,并使用散列算法(如 SHA256)进行处理以创建散列。

    5. 发送令牌:

    服务器将此令牌发送到客户端,客户端通常将其存储在浏览器中。

    6. 代币存储选项:

    客户端可以以不同的方式存储令牌,例如 HttpOnly Cookie、会话存储或本地存储。建议存储在 HttpOnly Cookies 中,因为它可以防止 JavaScript 访问,从而增强针对 XSS 攻击的安全性。

    7. 令牌到期和安全:

    令牌通常有一个过期时间以增强安全性。

    8. 在请求中包含 Token:

    对于向服务器发出的每个请求,客户端都会在授权标头中发送令牌。

    最好在令牌前加上“Bearer”前缀。

    axios.get(URL, {    headers: {        'Authorization': 'Bearer ' + token,    },})
    
    

    9. 服务器端验证:

    收到请求后,服务器检索令牌。

    10. 令牌验证和用户认证:

    使用密钥,服务器验证令牌并从中提取声明。如果声明中的用户信息存在于服务器的用户表中,则服务器会对用户进行身份验证,并授予对所请求资源的访问权限。

    代码例子

    //登录app.post('/login', (req, res) => {const { username, password } = req.body;  const user = users.find(u => u.username === username && u.password === password);  jwt.sign({ user }, secretKey, { expiresIn: '1h' }, (err, token) => {    if (err) {      res.status(500).send('Error generating token');    } else {      res.json({ token });    }  });});

    处理保护页面

    我们使用veriyToken()函数作为中间件来处理每条需要验证的路由。请求通过,veriyToken()并且仅当next()调用该函数时,它才会传递到该路由并实现代码。

    app.get('/dashboard', verifyToken, (req, res) => {  res.send('Welcome to the Home page');});// Verify token middlewarefunction verifyToken(req, res, next) {  const token = req.headers['authorization'];  if (typeof token !== 'undefined') {    jwt.verify(token.split(' ')[1], secretKey, (err, decoded) => {      if (err) {        res.status(403).send('Invalid token');      } else {        req.user = decoded.user;        next();      }    });  } else {    res.status(401).send('Unauthorized');  }}
    
    

    两种方法的差异

    • 存储位置:会话存储在服务器上,而令牌(JWT)存储在客户端。

    • 有状态与无状态:会话是有状态的,而令牌是无状态的,从而可以在分布式系统中实现更好的可扩展性。

    • 过期处理:会话过期由服务器管理,而令牌过期由令牌本身处理。

    • 安全措施:JWT 通常包括数字签名和加密支持,与使用 cookie 的典型会话机制相比增强了安全性,并且如果保护不当,可能容易受到 CSRF 攻击。

    • 使用灵活性:令牌 (JWT) 在携带身份验证之外的附加信息方面提供了更大的灵活性,对于授权和自定义数据传输非常有用。

    应该使用哪种方法?

    这取决于应用程序的要求和性质。大多数应用程序会使用混合方法,即针对 API 的基于令牌的身份验证,以及针对基于 Web 的交互的基于会话的身份验证。

    希望你喜欢这篇文章。如果对你有用,请不要忘记点赞转发!对了,你的项目使用哪种后端语言?欢迎在文底发表评论~🤔

    相关文章

    塑造我成为 CTO 之路的“秘诀”
    “人工智能教母”的公司估值达 10 亿美金
    教授吐槽:985 高校成高级蓝翔!研究生基本废了,只为房子、票子……
    Windows 蓝屏中断提醒开发者:Rust 比 C/C++ 更好
    Claude 3.5 Sonnet 在伽利略幻觉指数中名列前茅
    上海新增 11 款已完成登记生成式 AI 服务

    发布评论