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

ASP.NET Web API中JWT与Bearer Token的疑问及自定义生成方法

嘿,我来帮你把这些绕人的身份验证概念理清楚——你提到的这些点其实是很多刚接触API身份验证的开发者都会混淆的,咱们一个个拆解明白:

先搞懂:Bearer Token 到底是什么?

Bearer Token本质上是HTTP协议中定义的一种身份验证方案(RFC 6750标准),它不是具体的令牌格式,而是一个传输约定:告诉服务器“我持有这个令牌,你应该基于它来验证我的身份,允许我访问资源”。

你平时看到的Authorization: Bearer <token>这个HTTP头,就是这个标准的具体实现——Bearer是这个方案的名称,后面跟着的才是实际的令牌内容。

Bearer Token 是否自包含?能不能查看声明?

这里要划重点:Bearer Token只是传输方式,它的特性完全取决于背后的令牌格式:

  • 如果Bearer Token的载体是JWT,那它就是自包含的,客户端可以直接解析出Header和Payload里的声明数据(比如用户ID、角色、过期时间),不需要调用服务器接口。
  • 如果Bearer Token是“不透明令牌”(比如随机生成的字符串),那客户端完全看不到任何有效信息,只能拿着它去服务器验证,服务器自己存储着令牌和用户信息的映射关系。
那为什么要用Bearer Token?不用行不行?

当然可以自己搞一套,但Bearer Token是行业通用标准,好处太多了:

  • 所有遵循HTTP规范的框架、工具(比如Postman、Swagger、前端axios)都原生支持Authorization: Bearer <token>这种格式,兼容性拉满。
  • 不用自己定义奇怪的头或者参数,减少沟通和开发成本。
  • 标准意味着安全性有经过验证的最佳实践,比如HTTPS传输、令牌过期策略等。
有没有JWT Bearer Token这个说法?

必须有!这其实是现在最流行的组合:把JWT作为Bearer Token的载体。很多文档里提到的JWT Bearer Token,就是指用JWT来填充Bearer方案里的<token>部分——你平时在ASP.NET里用的JWT认证,本质上就是这套逻辑。

如何在ASP.NET Web API(MVC风格)里生成自定义Bearer Token?

分两种常见场景,你可以根据需求选:

场景1:生成基于JWT的Bearer Token(推荐,自包含、无状态)

这是现在的主流方案,步骤如下:

  1. 先安装必要的NuGet包:
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
Install-Package System.IdentityModel.Tokens.Jwt
  1. 在Startup.cs(.NET Framework/.NET Core 3.x)或Program.cs(.NET 6+)里配置JWT认证服务:
// .NET 6+ 示例
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "你的API发行方,比如https://yourapi.com",
            ValidAudience = "你的API受众,比如https://yourapi.com/api",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("你的安全密钥,要足够长,建议32位以上的随机字符串"))
        };
    });

builder.Services.AddAuthorization();
  1. 写一个生成JWT令牌的方法:
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

public class TokenService
{
    private readonly IConfiguration _config;

    public TokenService(IConfiguration config)
    {
        _config = config;
    }

    public string GenerateJwtBearerToken(string userId, string userName, string role = "User")
    {
        // 自定义声明(可以根据业务需求添加更多)
        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, userId),
            new Claim(JwtRegisteredClaimNames.UniqueName, userName),
            new Claim(ClaimTypes.Role, role),
            new Claim("CustomClaim", "你的自定义数据")
        };

        // 从配置里取密钥(不要硬编码!)
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        // 创建JWT令牌
        var token = new JwtSecurityToken(
            issuer: _config["Jwt:Issuer"],
            audience: _config["Jwt:Audience"],
            claims: claims,
            expires: DateTime.UtcNow.AddHours(1), // 设置过期时间
            signingCredentials: creds
        );

        // 序列化为字符串
        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}
  1. 客户端使用时,把生成的令牌放到HTTP头里:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...(你的JWT字符串)

场景2:生成不透明的Bearer Token(需要服务器存储令牌映射)

如果需要主动吊销令牌(JWT一旦签发就无法主动作废,只能等过期),可以用这种方案:

  1. 生成随机令牌并存储到缓存/数据库:
using StackExchange.Redis;

public class OpaqueTokenService
{
    private readonly IConnectionMultiplexer _redis;

    public OpaqueTokenService(IConnectionMultiplexer redis)
    {
        _redis = redis;
    }

    public string GenerateOpaqueBearerToken(string userId)
    {
        // 生成唯一随机令牌
        var token = Guid.NewGuid().ToString("N");
        var db = _redis.GetDatabase();
        // 存储令牌和用户ID的映射,设置1小时过期
        db.StringSet($"auth:token:{token}", userId, TimeSpan.FromHours(1));
        return token;
    }

    // 验证令牌的方法
    public string ValidateToken(string token)
    {
        var db = _redis.GetDatabase();
        return db.StringGet($"auth:token:{token}");
    }
}
  1. 写一个自定义认证中间件来验证令牌:
public class OpaqueTokenAuthMiddleware
{
    private readonly RequestDelegate _next;
    private readonly OpaqueTokenService _tokenService;

    public OpaqueTokenAuthMiddleware(RequestDelegate next, OpaqueTokenService tokenService)
    {
        _next = next;
        _tokenService = tokenService;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
        if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer "))
        {
            var token = authHeader.Substring(7);
            var userId = _tokenService.ValidateToken(token);
            if (!string.IsNullOrEmpty(userId))
            {
                // 创建用户身份
                var claims = new[] { new Claim(ClaimTypes.NameIdentifier, userId) };
                var identity = new ClaimsIdentity(claims, "OpaqueBearer");
                context.User = new ClaimsPrincipal(identity);
            }
        }

        await _next(context);
    }
}
  1. 在Startup.cs或Program.cs里注册中间件:
// .NET 6+ 示例
builder.Services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect("你的Redis连接字符串"));
builder.Services.AddSingleton<OpaqueTokenService>();

var app = builder.Build();

app.UseMiddleware<OpaqueTokenAuthMiddleware>();
app.UseAuthorization();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:58:14