.NET Core API添加JWT授权后401及无效令牌问题
问题分析与解决方案
1. 注册/登录接口被拦截的问题
不要给AuthenticationController整个控制器添加[Authorize]标记——登录、注册本身就是匿名访问的入口,应该将[Authorize]标记应用在需要保护的业务API控制器上。如果一定要给AuthenticationController加全局授权,必须在Register和Login两个Action上单独添加[AllowAnonymous],确保这两个接口能被匿名调用:
[ApiController] [Route("api/auth")] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class AuthenticationController : ControllerBase { // 允许匿名访问注册接口 [AllowAnonymous] [HttpPost("register")] public async Task<IActionResult> Register([FromBody] RegisterModel model) { // 注册逻辑 } // 允许匿名访问登录接口 [AllowAnonymous] [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginModel model) { // 登录并生成JWT逻辑 } }
2. JWT令牌格式错误(IDX14100)与MissingMethodException
2.1 排查JWT生成代码问题
IDX14100错误说明生成的令牌不是标准JWT格式(标准JWT为header.payload.signature三段式,用.分隔),检查Login接口中生成令牌的代码:
- 必须使用
JwtSecurityTokenHandler.WriteToken()方法将JwtSecurityToken对象转换为标准JWT字符串,不能直接返回ClaimsIdentity或其他对象。 - 确保生成令牌时的参数(Issuer、Audience、密钥)与Program.cs中的验证配置一致。
正确的JWT生成示例:
private string GenerateJwtToken(User user) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_configuration["Jwt:SecretKey"]); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), new Claim(ClaimTypes.Email, user.Email) }), Expires = DateTime.UtcNow.AddHours(2), Issuer = _configuration["Jwt:Issuer"], Audience = _configuration["Jwt:Audience"], SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); // 必须调用WriteToken生成标准JWT字符串 return tokenHandler.WriteToken(token); }
2.2 解决MissingMethodException异常
该异常通常由NuGet包版本不兼容导致:
- 确保
Microsoft.AspNetCore.Authentication.JwtBearer和System.IdentityModel.Tokens.Jwt的版本完全一致(比如均为6.0.25或7.0.14),版本不匹配会导致方法签名不兼容。 - 清理项目NuGet缓存,重新安装依赖包,避免版本冲突。
- 检查Program.cs中JWT配置代码是否符合当前.NET版本语法(以.NET 6+为例):
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.ASCII.GetBytes(builder.Configuration["Jwt:SecretKey"])) }; });
2.3 验证请求令牌的正确性
访问受保护API时,确保请求头格式正确:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiOiJqb2huQGRvbWFpbi5jb20iLCJleHAiOjE3MTk2MjQwMDAsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCJ9.SW9fX8Z1QZ8eUeX7R7R7R7R7R7R7R7R7R7R7R7R7
- 不要遗漏
Bearer前缀,令牌字符串不要包含多余空格或引号。 - 可以将生成的令牌复制到jwt.io解析,确认是否为有效JWT格式。
内容的提问来源于stack exchange,提问作者Julian Parra
相关产品推荐
相关产品推荐

