You need to enable JavaScript to run this app. 如何从System.IdentityModel的JwtSecurityToken提取Bearer Token并实现API鉴权
优惠活动
大模型
产品
解决方案
定价
更多

如何从System.IdentityModel的JwtSecurityToken提取Bearer Token并实现API鉴权

JWT 鉴权常见问题排查

你当前代码的核心认知误区

  • 你现在的Validated方法返回的是解析后的JwtSecurityToken实体对象,根本不是实际能用的Bearer Token。你贴出来的那段序列化JSON,就是把这个C#类对象直接序列化生成的结果,哪怕里面存了原始JWT的字段,也完全不符合鉴权的格式要求。
  • 真正的Bearer Token是一个纯字符串,标准结构是:三段式JWT原始字符串 + 固定的Bearer 前缀,最终形态类似:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYiLCJuYmYiOjE2MTg3MTQ3OTEsImV4cCI6MTYxODcyMTk5MSwiaWF0IjoxNjE4NzE0NzkxfQ.xxxxx。这个值是要放在HTTP请求的Authorization请求头里传递的,不是要后端方法序列化返回给前端的。
  • 换句话说:你写的Validated方法从一开始的定位就跑偏了,它本来的作用应该是校验传进来的字符串JWT是不是合法有效,根本不需要它“返回Bearer Token”——Bearer Token本身就是入参传进来的那个字符串,加上协议要求的前缀而已。

现有代码的可修正点

  • 如果在校验通过后需要拿到原始JWT字符串,根本不需要返回整个JwtSecurityToken对象:直接取入参的token值,或者读解析后对象的jwtToken.RawData字段就拿到了。
  • 代码里的catch (Exception e) { throw e; }写法完全是冗余的:这种写法会把原始异常的堆栈信息重置成当前方法的位置,排查问题的时候根本找不到真实报错点,直接删掉这个try-catch,或者把throw e;改成throw;就行。
  • 你最开始写的Authenticate登录方法的逻辑是对的:它返回的AuthToken.Token字段就是原始的三段式JWT字符串,前端拿到这个字符串之后,后续调用受保护接口的时候,自动给请求头加上Bearer 前缀拼上这个字符串传回来就行,不需要后端在登录接口里额外拼接前缀。

全局用Bearer Token保护API的正确配置

你知道在控制器顶部加[Authorize]的方向是对的,但如果没有提前把JWT鉴权的中间件配置好,光加这个特性是完全不生效的:

  1. 首先在服务注册阶段把JWT鉴权的逻辑统一配置好,不用在每个校验方法里重复写TokenValidationParameters:
    // .NET 6+ 示例写法
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_appSettings.Secret)),
                ValidateIssuer = false,
                ValidateAudience = false,
                ClockSkew = TimeSpan.Zero
            };
        });
    
  2. 然后在请求管道配置阶段注册中间件,注意中间件的顺序不能乱:必须在路由匹配之后、控制器映射之前挂载鉴权相关的中间件:
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    
  3. 配置完成之后,[Authorize]特性才会真正生效:如果请求没带合法的Authorization头,接口会直接返回401未授权。
  4. 如果不想每个控制器都手动加[Authorize],可以直接配置全局授权过滤器,让所有接口默认要求登录校验,只有需要开放匿名访问的接口,单独加[AllowAnonymous]特性就行:
    builder.Services.AddControllers(options =>
    {
        options.Filters.Add(new AuthorizeFilter());
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 07:06:09