ASP.NET Core 3.1 MVC JWT生成正常但请求始终返回401错误求助
问题根因及修复方案
1. 认证配置重复覆盖错误
ConfigureServices方法中两次调用了AddAuthentication方法,后注册的Cookie认证会覆盖之前的JWT认证默认配置,导致全局默认认证方案变为Cookie,携带JWT的请求自然无法通过认证。
2. 中间件执行顺序错误
Configure方法中认证和授权中间件顺序颠倒:必须先执行UseAuthentication完成身份校验,再执行UseAuthorization完成权限校验,顺序错误会导致授权逻辑拿不到认证信息直接返回401。
3. 多认证方案兼容问题
如果确实需要同时支持JWT和Cookie两种认证方式,不能重复调用AddAuthentication,需要合并配置。
具体修复代码
修改ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddCors(); services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN"); services.AddControllersWithViews(); services.AddRazorPages(); var tokenOptions = Configuration.GetSection("TokenOptions").Get<TokenOptions>(); // 合并认证配置,不要重复调用AddAuthentication services.AddAuthentication(options => { // 可根据业务设置默认方案,或者给接口单独指定认证方案 options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidIssuer = tokenOptions.Issuer, ValidAudience = tokenOptions.Audience, ValidateIssuerSigningKey = true, IssuerSigningKey = SecurityKeyHelper.CreateSecurityKey(tokenOptions.SecurityKey), // 可选:修复时区差问题,允许一定的时间偏移 ClockSkew = TimeSpan.FromMinutes(5) }; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o => { o.LoginPath = "/Auth/Login"; }); services.AddDependencyResolvers(new ICoreModule[] { new CoreModule() }); // 删除重复的services.AddControllersWithViews()调用 }
修改Configure方法的中间件顺序
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseCors(builder => builder.WithOrigins("https://localhost:44378").AllowAnyHeader().AllowAnyMethod()); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // 先执行认证,再执行授权,顺序不可颠倒 app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Customer}/{action=Index}/{id?}"); }); app.UseStatusCodePages(); }
其他注意事项
- 生成JWT时建议统一使用
DateTime.UtcNow代替DateTime.Now,避免时区差异导致的token过期校验失败 - 发起请求时
Authorization头格式必须正确:Bearer 你的token值,注意Bearer和token之间有且仅有一个空格 - 如果部分接口需要使用Cookie认证,给对应Controller/Action加上
[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]特性即可 - 如果部分接口需要使用JWT认证,给对应Controller/Action加上
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]特性即可
内容的提问来源于stack exchange,提问作者Damla Kayali
相关产品推荐
相关产品推荐

