ASP.NET Core 6 MVC:UseStatusCodePagesWithReExecute在Windows认证前重定向问题
解决方案
核心问题:中间件顺序错误
你的错误处理中间件(自定义或UseStatusCodePagesWithReExecute)被放在了认证中间件之前,导致Windows认证流程还未执行,就提前拦截了401状态码并跳转错误页,破坏了浏览器与服务器的认证挑战交互(正常情况下401应触发浏览器弹出Windows登录框或自动发送凭证)。
修复步骤
- 调整中间件顺序
将错误处理相关中间件移至UseAuthentication()和UseAuthorization()之后,确保认证授权流程先完成,再处理错误状态码。修改后的program.cs代码如下:
using Microsoft.AspNetCore.Authentication.Negotiate; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services .AddAuthentication(NegotiateDefaults.AuthenticationScheme) .AddNegotiate(); builder.Services.AddAuthorization(options => { options.FallbackPolicy = options.DefaultPolicy; }); builder.Services.AddRazorPages(); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); // 错误处理中间件移至认证授权之后 app.Use(async (context, next) => { await next(); var status = context.Response.StatusCode; // 仅当无认证挑战头时,才跳转错误页 if (status >= 400 && !context.Response.Headers.ContainsKey("WWW-Authenticate")) { context.Response.Redirect($"/Error/{status}"); } }); // 也可替换为UseStatusCodePagesWithReExecute,同样需放在认证授权之后 // app.UseStatusCodePagesWithReExecute("/Error/{0}"); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
区分认证挑战与真实错误
在自定义中间件中增加判断:如果响应包含WWW-Authenticate头,说明这是Windows认证的挑战请求(需要浏览器处理登录),此时不执行跳转;只有真正的无权限/错误(无该头的401)才跳转到错误页。确保错误页允许匿名访问
你的ErrorController已添加[AllowAnonymous]属性,这部分是正确的,避免跳转错误页时再次触发认证循环。
原理说明
Windows认证(Negotiate)通过返回带WWW-Authenticate: Negotiate头的401响应,触发浏览器自动发送Windows凭证或弹出登录框。如果错误处理中间件在认证前运行,会直接拦截这个401并跳转,打断认证流程。调整顺序后,认证流程优先执行,只有当认证完成后出现的真实错误(如凭证无效、无权限)才会被错误处理逻辑捕获。
内容的提问来源于stack exchange,提问作者Nina
相关产品推荐
相关产品推荐

