NodeJs学习日志(7):JWT学习

NodeJs学习日志(7):JWT学习

八股文

什么是JWT?

JWT(JSON Web Token)是一种 基于 JSON 的开放标准(RFC 7519),用于在客户端和服务器之间安全地传递声明(Claims)。它本质上是一个经过加密签名的字符串,包含了用户身份信息和其他元数据,服务器无需存储会话状态,仅通过验证 Token 的有效性即可完成身份认证。

JWT 的结构(三段式)

一个完整的 JWT 由 Header(头部)、Payload(载荷)、Signature(签名) 三部分组成,用 . 分隔,格式如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwidXNlcklkIjoiMTIzNDU2IiwiaWF0IjoxNzM0NTYwMDYxLCJleHAiOjE3MzQ1NjM2NjF9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  1. Header(头部)
    指定算法和令牌类型,默认使用 Base64 编码(可逆)
{
  "alg": "HS256", // 加密算法(如 HS256、RS256)
  "typ": "JWT"    // 令牌类型
}
  1. Payload(载荷)
    存储核心数据(用户信息、过期时间等),同样使用 Base64 编码(注意:Base64 是编码不是加密,不要存储敏感信息!)
    内置的标准声明(可选):​
    iat:令牌签发时间(时间戳)​
    exp:令牌过期时间(时间戳)​
    sub:令牌主题(通常是用户 ID)​
    自定义声明:如 username、userId 等业务字段

  2. Signature(签名)
    由 Header + Payload + 密钥(Secret Key)通过指定算法加密生成,用于验证令牌的完整性和真实性。

JWT 的核心功能

  1. 无状态身份认证​
    服务器无需存储用户会话信息,仅通过验证 Token 签名即可确认用户身份,降低了服务器存储压力,尤其适合分布式系统和微服务。​
  2. 跨域认证​
    Token 是自包含的,可通过 HTTP 请求头(如 Authorization: Bearer )传递,轻松支持跨域场景(如前端部署在 xxx.com,后端部署在 api.xxx.com)。​
  3. 数据传输​
    Payload 可携带非敏感业务数据(如用户昵称、角色),减少后端查询数据库的次数,提升接口性能。​
  4. 令牌刷新​
    支持在 Token 过期前或过期后,通过旧 Token 生成新 Token(需保证旧 Token 未被篡改),避免用户频繁登录。

使用

安装

npm install jsonwebtoken

代码

const jwt = require('jsonwebtoken');

// 生成强密钥(生产环境应从环境变量读取)
const generateSecretKey = () => {
  return crypto.randomBytes(64).toString('hex');
};

console.log("生成密钥:", generateSecretKey());

//jwt配置,
const JWT_OPTIONS = {
    SECRET_KEY: "secret-key", // 密钥
    EXPIRES_IN: '1h',//过期时间
    ALGORITHM: 'HS256' // 加密方式
};

//等待加密的载荷
const payload = {
    username: "admin",
    userId: "123456"
}

// 生成JWT
function generateToken(payload) {
    const token = jwt.sign(payload, JWT_OPTIONS.SECRET_KEY, {
        expiresIn: JWT_OPTIONS.EXPIRES_IN,
        algorithm: JWT_OPTIONS.ALGORITHM
    });
    return token;
}

let token = generateToken(payload);
console.log("生成的Token:", token);

// 验证JWT
function verifyToken(token) {
    try {
        const decoded = jwt.verify(token, JWT_OPTIONS.SECRET_KEY, {
            algorithms: [JWT_OPTIONS.ALGORITHM]
        });
        console.log("Token验证成功:", decoded);
        return { valid: true, decoded };
    } catch (error) {
        if (error.name === 'TokenExpiredError') {
            console.log("Token已过期:", error.expiredAt);
            return { valid: false, error: 'TOKEN_EXPIRED' };
        } else if (error.name === 'JsonWebTokenError') {
            console.log("Token无效:", error.message);
            return { valid: false, error: 'INVALID_TOKEN' };
        } else {
            console.log("Token验证失败:", error.message);
            return { valid: false, error: 'VERIFICATION_FAILED' };
        }
    }
}


verifyToken(token);

// 刷新JWT
function refreshToken(token) {
    const verificationResult = verifyToken(token);

    if (!verificationResult.valid && verificationResult.error !== 'TOKEN_EXPIRED') {
        throw new Error('无法刷新无效的Token');
    }

    // 即使token过期,我们也尝试解码获取payload(不验证过期)
    const decoded = jwt.decode(token);
    if (!decoded) {
        throw new Error('无法解码Token');
    }

    // 移除原有的过期时间和其他jwt属性,保留原始数据
    const { iat, exp, ...payload } = decoded;
    console.log("decoded" + JSON.stringify(decoded));
    const { username, userId } = decoded;
    console.log("username" + username);
    console.log("userId" + userId); 
    const newToken = generateToken(payload);
    console.log("刷新的Token:", newToken);
    return newToken;
}

refreshToken(token);

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值