为端点添加[authorize]后返回401,JWT认证异常求助
JWT认证返回401未授权排查求助
给API端点添加[Authorize]特性后,访问始终返回401未授权错误。JWT令牌在jwt.io验证正常,但后端中间件日志显示认证失败:先提示“Token is null or empty”,随后抛出SecurityTokenMalformedException(提示JWT格式不正确),内部嵌套MissingMethodException,找不到Microsoft.IdentityModel.Tokens.Base64UrlEncoder.UnsafeDecode(System.ReadOnlyMemory1
中间件日志
Twyt.Twyt.Api.Middleware.RequestLoggingMiddleware: Information: Handling request: GET /api/Post/user/82d3f35b-aa00-453b-80f5-2c06f2063e60 Twyt.Twyt.Api.Middleware.RequestLoggingMiddleware: Information: Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI4MmQzZjM1Yi1hYTAwLTQ1M2ItODBmNS0yYzA2ZjIwNjNlNjAiLCJqdGkiOiJjYzYwZWNlMi0wZDE0LTQ3NWEtOTcxOC00NWYwMzhiM2VhZmIiLCJleHAiOjE3MjY0MTc1NDksImlzcyI6IlR3eXQiLCJhdWQiOiJUd3l0In0.UN8rtNhp6HI7Ut6ovUOTYBFmYHneHHbN8XblZRZ3PlU Program: Warning: Token is null or empty Loaded Assembly '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Diagnostics.StackTrace.dll' Loading module /usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Diagnostics.StackTrace.dll in application domain 1:clrhost Pdb file for assembly /usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Diagnostics.StackTrace.dll was not found or failed to read Loaded Assembly '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Reflection.Metadata.dll' Loading module /usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Reflection.Metadata.dll in application domain 1:clrhost Pdb file for assembly /usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Reflection.Metadata.dll was not found or failed to read Loaded Assembly '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Collections.Immutable.dll' Loading module /usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Collections.Immutable.dll in application domain 1:clrhost Pdb file for assembly /usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.8/System.Collections.Immutable.dll was not found or failed to read Program: Error: Authentication failed: Microsoft.IdentityModel.Tokens.SecurityTokenMalformedException: IDX14100: JWT is not well formed, there are no dots (.). The token needs to be in JWS or JWE Compact Serialization Format. (JWS): 'EncodedHeader.EndcodedPayload.EncodedSignature'. (JWE): 'EncodedProtectedHeader.EncodedEncryptedKey.EncodedInitializationVector.EncodedCiphertext.EncodedAuthenticationTag'. ---> System.MissingMethodException: Method not found: 'Byte[] Microsoft.IdentityModel.Tokens.Base64UrlEncoder.UnsafeDecode(System.ReadOnlyMemory`1<Char>)'. at Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.ReadToken(String encodedJson) at Microsoft.IdentityModel.JsonWebTokens.JsonWebToken..ctor(String jwtEncodedString) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ReadToken(String token, TokenValidationParameters validationParameters) --- End of inner exception stack trace --- Program: Warning: OnChallenge error: invalid_token Twyt.Twyt.Api.Middleware.RequestLoggingMiddleware: Information: Finished handling request. Status code: 401 Twyt.Twyt.Api.Middleware.RequestLoggingMiddleware: Warning: Unauthorized access attempt: GET /api/Post/user/82d3f35b-aa00-453b-80f5-2c06f2063e60
Program.cs中的JWT认证配置
builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { var key = Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"] ?? throw new InvalidOperationException("JWT Key is not configured")); options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"] ?? throw new InvalidOperationException("JWT Issuer is not configured"), ValidAudience = builder.Configuration["Jwt:Audience"] ?? throw new InvalidOperationException("JWT Audience is not configured"), IssuerSigningKey = new SymmetricSecurityKey(key) }; options.IncludeErrorDetails = true; options.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>(); logger.LogError("Authentication failed: {Exception}", context.Exception.ToString()); return Task.CompletedTask; }, OnChallenge = context => { var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>(); logger.LogWarning("OnChallenge error: {0}", context.Error); return Task.CompletedTask; }, OnMessageReceived = context => { var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>(); var token = context.Token; if (string.IsNullOrEmpty(token)) { logger.LogWarning("Token is null or empty"); return Task.CompletedTask; } // Log the raw token for debugging logger.LogInformation("Token received: {Token}", token); return Task.CompletedTask; } }; }); builder.Services.AddAuthorization();
GenerateJwtToken令牌生成函数
public async Task<string> GenerateJwtToken(User user) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, user.UserId.ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var token = new JwtSecurityToken( _configuration["Jwt:Issuer"], _configuration["Jwt:Audience"], claims, expires: DateTime.Now.AddHours(2), signingCredentials: credentials ); return new JwtSecurityTokenHandler().WriteToken(token); }
排查解决方案
统一NuGet包版本
核心错误MissingMethodException表明运行时找不到指定方法,大概率是Microsoft.IdentityModel.Tokens、Microsoft.AspNetCore.Authentication.JwtBearer等相关包版本与.NET 8 runtime不兼容。- 执行
dotnet list package查看当前包版本,确保所有IdentityModel相关包版本统一,且适配.NET 8(建议使用8.x系列版本)。 - 通过
dotnet add package <PackageName> --version <CompatibleVersion>命令升级或统一包版本,比如:dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 8.0.8 dotnet add package Microsoft.IdentityModel.Tokens --version 8.0.2
- 执行
修复令牌读取逻辑
日志显示请求头存在Bearer令牌,但OnMessageReceived中context.Token为空,说明中间件未正确提取令牌。可以手动从请求头获取并赋值:OnMessageReceived = context => { var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>(); var authHeader = context.HttpContext.Request.Headers.Authorization.FirstOrDefault(); if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer ")) { context.Token = authHeader.Substring("Bearer ".Length).Trim(); logger.LogInformation("Token received: {Token}", context.Token); } else { logger.LogWarning("Token is null or empty"); } return Task.CompletedTask; }验证令牌传输完整性
确认Swagger发送请求时,Authorization头严格遵循Bearer <Token>格式,无多余空格、换行或特殊字符。可以直接复制日志中的令牌到jwt.io再次验证,排除传输过程中的篡改问题。
内容的提问来源于stack exchange,提问作者Abdou El Mesnaoui
相关产品推荐
相关产品推荐

