You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加密JwtSecurityToken?实现JWT令牌的生成与验证

JWT 令牌的签名加密、生成与验证实现

一、先搞懂JWT的“加密”到底是什么

首先得明确:JWT本身的Header和Payload部分是Base64Url编码(不是加密,别人拿到可以解码看到内容),我们说的“加密JwtSecurityToken”其实是指给令牌添加数字签名——用来防止令牌被篡改,同时验证令牌的合法性。

常用的签名方案是对称加密算法比如HmacSha256:

  • 生成令牌时,用密钥(SymmetricSecurityKey)对Header+Payload的组合进行哈希签名
  • 验证令牌时,用同样的密钥重新计算签名,和令牌里的签名对比,一致就说明令牌没被篡改且来源合法

二、完整实现JWT令牌的生成与验证

1. 令牌生成(补全你提供的代码)

你给出的代码已经覆盖了核心环节,我帮你补全完整的生成逻辑:

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

// 假设_appSettings是你的配置类,包含Token.Key(签名密钥)、Token.ExpiresIn(过期时长,比如3600秒)等配置项
var user = await this._applicationUserProvider.GetCurrentUserAsync();

// 构建令牌携带的用户声明(Claims)
var claims = new[]
{
    new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
    new Claim(JwtRegisteredClaimNames.NameId, user.Id),
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
    // 可按需添加自定义声明,比如用户角色
    new Claim(ClaimTypes.Role, user.Role)
};

// 生成对称签名密钥
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Token.Key));
// 配置签名凭证(指定算法+密钥)
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

// 创建JwtSecurityToken实例
var token = new JwtSecurityToken(
    issuer: _appSettings.Token.Issuer, // 令牌颁发者(可选,验证阶段会用到)
    audience: _appSettings.Token.Audience, // 令牌受众(可选,验证阶段会用到)
    claims: claims,
    expires: DateTime.UtcNow.AddSeconds(_appSettings.Token.ExpiresIn), // 设置过期时间
    signingCredentials: creds
);

// 生成最终的令牌字符串
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);

2. 令牌验证实现

验证令牌需要配置TokenValidationParameters,然后通过JwtSecurityTokenHandler完成验证逻辑:

public bool ValidateToken(string token)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var validationParameters = new TokenValidationParameters
    {
        // 启用签名验证
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Token.Key)),
        // 可选:验证令牌颁发者
        ValidateIssuer = true,
        ValidIssuer = _appSettings.Token.Issuer,
        // 可选:验证令牌受众
        ValidateAudience = true,
        ValidAudience = _appSettings.Token.Audience,
        // 验证令牌过期时间
        ValidateLifetime = true,
        // 允许的时钟偏差(处理服务器时间差问题)
        ClockSkew = TimeSpan.Zero
    };

    try
    {
        // 验证令牌,成功会返回包含用户声明的ClaimsPrincipal
        var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
        // 可按需强转成JwtSecurityToken,获取令牌头、算法等额外信息
        var jwtToken = validatedToken as JwtSecurityToken;
        if (jwtToken != null && jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
        {
            return true;
        }
        return false;
    }
    catch (SecurityTokenException)
    {
        // 令牌无效(过期、签名错误、颁发者/受众不匹配等)
        return false;
    }
}

关键注意事项

  • 签名密钥要足够长且保密:建议用至少32位的随机字符串,绝对不能硬编码到代码里,要存在配置文件或专业密钥管理服务中
  • 过期时间设置要合理:太短会频繁要求用户重新登录,太长会增加令牌泄露的风险
  • 如果需要真正加密Payload(让他人无法解码查看内容),可以使用JWE(JSON Web Encryption),不过大部分业务场景下,带签名的JWS就足够满足需求

内容的提问来源于stack exchange,提问作者Greg Gum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:14:22