MST

星途 面试题库

面试题:安全认证之JWT基础实现

请阐述在后端开发中,基于JWT实现身份验证的基本步骤,包括生成JWT、在请求中传递JWT以及验证JWT的流程,并简单说明JWT的结构组成。
32.2万 热度难度
后端开发安全认证

知识考点

AI 面试

面试题答案

一键面试

基于JWT实现身份验证的基本步骤

  1. 生成JWT
    • 用户在客户端输入用户名和密码进行登录。
    • 后端接收到登录请求,验证用户名和密码。若验证成功,从数据库中获取用户相关信息(如用户ID、用户名、角色等)。
    • 使用JWT库(如在Java中使用jjwt库),将用户信息作为负载(payload),选择一种加密算法(如HS256),并使用一个密钥(secret key)来生成JWT。例如在Python中使用PyJWT库:
import jwt
from datetime import datetime, timedelta

# 假设用户信息
user_info = {'user_id': 1, 'username': 'testuser', 'role': 'admin'}
# 密钥
secret_key = 'your_secret_key'
# 生成JWT
expiration = datetime.utcnow() + timedelta(minutes=30)
payload = {**user_info, 'exp': expiration}
token = jwt.encode(payload, secret_key, algorithm='HS256')
  1. 在请求中传递JWT
    • 后端将生成的JWT作为响应返回给客户端。
    • 客户端收到JWT后,通常将其存储在本地(如localStorage、sessionStorage或cookie中,但出于安全考虑,不建议使用cookie存储JWT)。
    • 后续客户端发起的每一个需要身份验证的请求,都要在请求头(Authorization header)中传递JWT,格式通常为 Bearer <JWT>。例如在JavaScript中使用fetch发送请求:
const token = localStorage.getItem('jwt_token');
fetch('your_api_endpoint', {
    headers: {
        'Authorization': `Bearer ${token}`
    }
})
  1. 验证JWT
    • 后端接收到带有JWT的请求,从请求头中提取JWT。
    • 使用相同的JWT库和密钥,对JWT进行验证。验证过程包括:检查JWT的格式是否正确、签名是否有效以及JWT是否过期。若验证成功,则可以从JWT的负载中获取用户信息,用于后续的权限控制等操作。例如在Node.js中使用jsonwebtoken库:
const jwt = require('jsonwebtoken');
const secret_key = 'your_secret_key';
const token = req.headers['authorization'].split(' ')[1];
try {
    const decoded = jwt.verify(token, secret_key);
    // decoded包含了JWT负载中的用户信息
    console.log(decoded);
} catch (err) {
    // 验证失败,返回错误响应
    res.status(401).send('Unauthorized');
}

JWT的结构组成

JWT由三部分组成,通过点(.)分隔,分别是:

  1. Header(头部)
    • 包含两部分信息:令牌的类型(即JWT)和使用的签名算法,如 {"alg": "HS256", "typ": "JWT"}
    • 然后将这个JSON对象进行Base64Url编码,形成JWT的第一部分。
  2. Payload(负载)
    • 包含声明(claims),这些声明是关于实体(通常是用户)和其他数据的陈述。例如用户ID、用户名、角色、过期时间等。分为三种类型:注册声明(如iss、exp、sub等)、公共声明和私有声明。
    • 同样将这个JSON对象进行Base64Url编码,形成JWT的第二部分。
  3. Signature(签名)
    • 要创建签名部分,需要使用编码后的Header、编码后的Payload、一个密钥和Header中指定的签名算法。例如使用HS256算法,签名的计算方式为:HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key )
    • 签名用于验证消息在传递过程中没有被更改,并且在使用私钥签名的情况下,还可以验证JWT的发送者的身份。