ASP.NET Web API中JWT认证返回401错误的排查求助
ASP.NET Web API JWT认证始终返回401未授权错误
在ASP.NET Web API接口添加[Authorize]特性后,使用JWT令牌进行身份认证时,始终收到401未授权错误。
我的项目配置
using FluentValidation; using FluentValidation.AspNetCore; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.FileProviders; using Server.Api.Extensions; using Server.Api.Middlewares; using Server.Domain.Interfaces; using Server.Domain.Services; using Server.Infrastructure; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("AveAnticaDbContextConnection") ?? throw new InvalidOperationException("Connection string 'AzureDbConnection' not found."); ConfigurationManager configuration = builder.Configuration; builder.Services.AddDbContext<AveAnticaDbContext>(x => x.UseSqlServer(connectionString)); builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>)); builder.Services.AddControllers(); builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddFluentValidationAutoValidation(); builder.Services.AddValidatorsFromAssemblies(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddScoped<IProductService, ProductService>(); builder.Services.AddScoped<IImageService, ImageService>(); builder.Services.AddScoped<ICategoryService, CategoryService>(); builder.Services.AddScoped<ILanguageService, LanguageService>(); builder.Services.AddScoped<ITagService, TagService>(); builder.Services.AddScoped<ILikesService, LikesService>(); builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddScoped<IAccountService, AccountService>(); builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); builder.Services.AddAuthentication(); builder.Services.ConfigureIdentity(); builder.Services.ConfigureJWT(builder.Configuration); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.ConfigureSwagger(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseCors(options => { options.AllowAnyHeader(); options.AllowAnyMethod(); options.AllowAnyOrigin(); }); app.UseMiddleware<JwtTokenMiddleware>(); app.UseMiddleware<ExceptionMiddleware>(); app.UseHttpsRedirection(); //app.UseResponseCaching(); app.UseAuthentication(); app.UseAuthorization(); var directPath = "Uploads";//builder.Configuration.GetConnectionString("Path"); app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider( Path.Combine(builder.Environment.ContentRootPath, directPath)), RequestPath = "/" + directPath }); app.MapControllers(); app.Run();
配置扩展类
public static class ServiceExtension { public static void ConfigureIdentity(this IServiceCollection services) { var builder = services.AddIdentity<Customer, IdentityRole>(o => { o.Password.RequireDigit = false; o.Password.RequireLowercase = false; o.Password.RequireUppercase = false; o.Password.RequireNonAlphanumeric = false; o.User.RequireUniqueEmail = true; }) .AddEntityFrameworkStores<AveAnticaDbContext>() .AddDefaultTokenProviders(); } public static void ConfigureJWT(this IServiceCollection services, IConfiguration configuration) { var jwtConfig = configuration.GetSection("JwtOptions"); var secretKey = jwtConfig["Key"]; services.AddAuthentication(opt => { opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateLifetime = true, ValidateAudience = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtConfig["Issuer"], ValidAudience = jwtConfig["Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)) }; }); } public static void ConfigureSwagger(this IServiceCollection services) { services.AddSwaggerGen(option => { option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo API", Version = "v1" }); option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Please enter a valid token", Name = "Authorization", Type = SecuritySchemeType.Http, BearerFormat = "JWT", Scheme = "Bearer" }); option.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type=ReferenceType.SecurityScheme, Id="Bearer" } }, new string[]{} } }); }); } }
账户服务(令牌生成相关代码)
public async Task<string> CreateTokenAsync(Customer user) { var signingCredentials = GetSigningCredentials(); var claims = await GetClaims(user); var tokenOptions = GenerateTokenOptions(signingCredentials, claims); return new JwtSecurityTokenHandler().WriteToken(tokenOptions); } private SigningCredentials GetSigningCredentials() { var jwtConfig = configuration.GetSection("JwtOptions"); var key = Encoding.UTF8.GetBytes(jwtConfig["Key"]); var secret = new SymmetricSecurityKey(key); return new SigningCredentials(secret, SecurityAlgorithms.HmacSha256); } private async Task<List<Claim>> GetClaims(Customer user) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.UserName) }; var roles = await userManager.GetRolesAsync(user); foreach (var role in roles) { claims.Add(new Claim(ClaimTypes.Role, role)); } return claims; }
JWT配置(appsettings.json)
"JwtOptions": { "Issuer": "AveAntica", "Lifetime": 12, "Audience": "AveAnticaAudience", "Key": "1234234rearaeta4wa4rras4tra" },
已尝试的排查步骤
- 同时使用
[Authorize]和[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]特性,问题依旧 - 确认请求中已正确传递JWT令牌,且解码后内容正常
- 对比运行正常的同类项目配置,调整自身配置无效
- 更新所有相关NuGet包,问题仍未解决
需要协助排查此JWT认证401错误的原因。
内容的提问来源于stack exchange,提问作者Georgiy
相关产品推荐
相关产品推荐

