.NET 6 Blazor应用部署IIS出现需认证用户授权失败如何解决
问题现象
- .NET 6 Blazor 托管式应用(含服务端、WASM客户端)部署到IIS后,访问根站点 http://blazorecommerceapi.findingsteve.net 触发授权错误,日志输出如下:
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

- 访问站点下API接口 http://blazorecommerceapi.findingsteve.net/api/product 同样返回异常:

- 项目本地运行时所有功能符合预期:Blazor客户端页面可正常打开,API接口数据可正常获取


现有配置
项目采用Sqlite实现数据持久化,认证相关逻辑在Program.cs中配置,核心代码如下:
builder.Services.AddScoped<IAuthService, AuthService>(); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8 .GetBytes(builder.Configuration.GetSection("AppSettings:Token").Value)), ValidateIssuer = false, ValidateAudience = false }; }); app.UseAuthentication(); app.UseAuthorization();
本地运行时JWT认证逻辑工作正常,仅部署到IIS后触发DenyAnonymousAuthorizationRequirement校验失败,提示需要已认证用户。
根因排查与解决方案
这类本地运行正常、IIS部署后触发匿名授权拦截的问题,按以下优先级排查即可解决:
1. 中间件顺序错误(最高发)
问题原因:ASP.NET Core中间件严格按照代码编写顺序执行,如果UseAuthorization/UseAuthentication放在了UseStaticFiles、UseBlazorFrameworkFiles之前,Blazor客户端依赖的静态资源(_framework目录下的WASM运行时、程序集、入口页面等)、公开接口都会被授权中间件拦截,要求认证。本地开发服务器对静态资源有特殊处理逻辑,不会触发该问题,生产环境部署后会直接复现。
修复方案:调整Program.cs中的中间件顺序,严格按照以下逻辑排列:
// 优先处理请求重定向、静态资源 app.UseHttpsRedirection(); app.UseBlazorFrameworkFiles(); // Blazor WASM托管模式必须添加,且放在静态文件中间件前 app.UseStaticFiles(); // 必须放在认证、授权中间件之前 // 再处理路由、认证、授权逻辑 app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); // 最后映射端点 app.MapControllers(); app.MapFallbackToFile("index.html"); // Blazor前端路由回退必须放在端点配置最后
如果项目配置了全局授权过滤器,需要给公开接口、静态资源路径添加[AllowAnonymous]特性,或在授权策略中直接排除对应路径。
2. 生产环境缺失JWT密钥配置
问题原因:本地开发时JWT密钥通常配置在appsettings.Development.json中,发布到IIS后项目默认加载appsettings.Production.json配置,如果该文件中未配置AppSettings:Token字段,会导致JWT签名密钥取值为空,认证中间件无法正常解析请求携带的Token,所有标记[Authorize]的端点都会直接返回未认证。如果同时配置了全局授权策略,连匿名可访问的资源也会被拦截。
修复方案:
- 检查发布目录下的
appsettings.Production.json,确认存在和开发环境一致的AppSettings:Token配置,且密钥长度符合对称加密要求(至少16位) - 给IIS应用程序池对应的运行身份授予配置文件的读取权限,避免配置加载失败
- 可在JWT配置中增加空值判断,发布时如果密钥为空直接抛出异常,避免静默失败:
var tokenKey = builder.Configuration.GetSection("AppSettings:Token").Value ?? throw new ArgumentNullException("JWT密钥未在生产配置中设置"); IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(tokenKey))
3. IIS身份验证模块冲突
问题原因:IIS默认会加载多套身份验证模块,如果部署时手动开启了Windows身份验证、ASP.NET模拟,或者禁用了匿名身份验证,会和应用内的JWT认证逻辑冲突:要么IIS直接拦截匿名请求返回401,要么Windows身份覆盖JWT认证生成的用户身份,导致授权校验失败。
修复方案:
- 打开IIS管理器,找到对应站点的「身份验证」功能面板
- 确保匿名身份验证为启用状态
- 禁用Windows身份验证、ASP.NET模拟、表单身份验证等其他所有身份验证模块
- 确认对应应用程序池的.NET CLR版本设置为「无托管代码」,符合ASP.NET Core部署要求
4. 目录权限配置错误
问题原因:
- Sqlite数据库文件所在目录,未给IIS应用程序池运行身份(默认格式为
IIS AppPool\你的应用池名称)授予读写权限,导致认证流程中查询用户信息失败,无法构造有效认证身份 - Blazor静态文件所在的
wwwroot目录未授予读取权限,导致静态资源请求返回401/403,被误认为授权逻辑异常
修复方案:给站点根目录、Sqlite数据库文件所在目录、wwwroot目录,添加对应应用池身份的读取权限,数据库目录额外授予写入权限。
内容的提问来源于stack exchange,提问作者Steve

