c# 如何实现jwt认证

来源:这里教程网 时间:2026-02-21 17:37:31 作者:

JWT 认证在 ASP.NET Core 中怎么配中间件

ASP.NET Core 6+ 默认不内置 JWT 验证逻辑,必须手动注册

Authentication
服务并配置
Bearer
方案。漏掉
AddAuthentication().AddJwtBearer()
这一步,所有带
[Authorize]
的接口都会直接返回 401,且不会进控制器。

关键点:

AddJwtBearer()
必须在
AddControllers()
之前调用,否则认证服务不可用
TokenValidationParameters
中的
ValidateIssuerSigningKey
ValidateAudience
ValidateIssuer
默认为
true
,若没配对应值(比如
ValidAudience
),token 会直接被拒
签名密钥必须是
SecurityKey
类型,不能直接传字符串;常用
new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-32-byte-secret"))
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
            ValidateIssuer = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidateAudience = true,
            ValidAudience = builder.Configuration["Jwt:Audience"],
            ClockSkew = TimeSpan.Zero // 关闭默认 5 分钟宽限,避免时间不同步误判过期
        };
    });

如何生成 JWT token 并返回给前端

生成 token 是纯内存操作,不需要数据库或外部服务。核心是用

JwtSecurityTokenHandler
+
SecurityTokenDescriptor
构建并序列化。

注意几个易错细节:

Expires
必须是
DateTime.UtcNow
加偏移,写成
DateTime.Now
在服务器时区非 UTC 时会导致 token 提前失效
SigningCredentials
的算法必须和中间件里
IssuerSigningKey
匹配,常见错误是中间件用
HMAC-SHA256
,但生成时用了
RSA
不要把密码、敏感字段塞进 payload;只放必要标识,如
uid
role
,且建议用标准声明名(
sub
roles
)方便框架识别
var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(new[]
    {
        new Claim(ClaimTypes.Name, user.UserName),
        new Claim(ClaimTypes.Role, "User"),
        new Claim("uid", user.Id.ToString())
    }),
    Expires = DateTime.UtcNow.AddMinutes(30),
    SigningCredentials = new SigningCredentials(
        new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)),
        SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
string token = tokenHandler.WriteToken(securityToken);

为什么 [Authorize] 不生效或报 401

最常见原因不是代码写错,而是请求头没对上。JWT 认证中间件默认只认

Authorization: Bearer <token></token>
格式,任意偏差都会跳过验证。

排查清单:

前端是否漏了
Bearer 
前缀(注意后面有个空格)?只传
xxx.yyy.zzz
会被完全忽略
请求头字段名是否拼错?比如写成
authorization
小写(.NET Core 默认大小写敏感)、
Auth
Token
token 是否已过期?用 jwt.io 手动解码看
exp
字段,对比服务器当前 UTC 时间
中间件是否注册在
UseRouting()
之后、
UseEndpoints()
之前?顺序错会导致认证不执行

如何从 Controller 里获取当前用户信息

认证成功后,

User
属性就是解析好的
ClaimsPrincipal
,所有 payload 里的 claim 都能直接读。别再查数据库找用户——JWT 本身已携带可信身份数据。

安全提醒:

不要依赖
User.Identity.Name
做权限判断,它只是
name
claim 的别名;应明确用
User.FindFirst("uid")?.Value
User.IsInRole("Admin")
如果前端伪造 token(比如改签发者),只要密钥没泄露,
JwtSecurityTokenHandler
会在验证阶段直接抛
SecurityTokenInvalidSignatureException
,不会让非法请求进到 action
需要访问原始 token 字符串?用
HttpContext.Request.Headers["Authorization"]
拿,然后手动截取
Bearer 
后内容——但绝大多数场景不需要

复杂点在于:token 一旦签发就不可撤销,要实现“主动登出”得靠服务端黑名单或缩短有效期,这不是 JWT 协议本身支持的。

相关推荐