如何修复IIS中.NET 6的预检请求不允许重定向错误
问题描述
- 两个应用:Blazor开发的UI应用、.NET 6开发的API应用
- 同一主域名下的不同子域名,本地调试正常,部署到IIS后触发CORS错误
- 错误信息:
Login_Register:1 Access to fetch at 'https://ajabk.' from origin 'https://aja.' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request
现有program.cs代码
var builder = WebApplication.CreateBuilder(args); var MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddCors(options => { options.AddPolicy(MyAllowSpecificOrigins, builder => { builder.SetIsOriginAllowed(isOriginAllowed: _ => true).AllowAnyHeader().AllowAnyMethod(); }); }); var app = builder.Build(); /*app.UseCors(x => x .AllowAnyMethod() .AllowAnyHeader() .SetIsOriginAllowed(origin => true) // allow any origin .AllowCredentials());*/ // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment() || app.Environment.IsProduction()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHsts(); app.UseMiddleware<AuthenticationMiddleWare>(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); app.UseCors(MyAllowSpecificOrigins); app.MapControllers(); app.Run();
问题分析与解决方案
错误核心是预请求(OPTIONS方法)被IIS或应用重定向了,浏览器的CORS规则明确禁止预请求出现重定向,直接拦截这类响应。
1. 修正中间件顺序(最关键)
.NET 6的中间件执行顺序严格,UseCors必须放在UseRouting之后、UseAuthorization和自定义中间件之前,否则CORS头无法正确注入到预请求响应里。调整后的代码:
var app = builder.Build(); // 环境判断 if (app.Environment.IsDevelopment() || app.Environment.IsProduction()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHsts(); // 先处理转发头 app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); app.UseStaticFiles(); app.UseRouting(); // 把UseCors移到这里,确保在认证和授权中间件之前 app.UseCors(MyAllowSpecificOrigins); app.UseMiddleware<AuthenticationMiddleWare>(); app.UseAuthorization(); app.MapControllers(); app.Run();
2. 排除OPTIONS请求的IIS重定向
如果你的API站点设置了HTTP转HTTPS的重定向,默认规则会把OPTIONS请求也一并重定向,导致预请求失败。在API的web.config里修改重定向规则,排除OPTIONS方法:
<rule name="HTTP to HTTPS redirect" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="off" /> <add input="{REQUEST_METHOD}" pattern="OPTIONS" negate="true" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /> </rule>
3. 修复前端API地址配置
错误信息里的API地址是https://ajabk.(末尾带点,无效),大概率是前端的API基础地址配置错误,导致请求发送到无效地址触发重定向。检查Blazor应用里的API地址配置,确保是完整有效的域名(比如https://ajabk.yourdomain.com)。
4. 优化CORS策略(可选,提升安全性)
不要直接允许所有来源,改成只允许你的主域名下的子域名,同时如果需要携带Cookie或认证信息,要加上AllowCredentials():
builder.Services.AddCors(options => { options.AddPolicy(MyAllowSpecificOrigins, builder => { builder.SetIsOriginAllowed(origin => { // 替换成你的主域名,只允许该域名下的子域名跨域 var host = new Uri(origin).Host; return host.EndsWith(".yourdomain.com"); }) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); });
总结
先排查前端API地址是否正确,再调整中间件顺序,最后检查IIS重定向规则是否排除了OPTIONS请求,基本就能解决这个问题。
内容的提问来源于stack exchange,提问作者mohammad asadi

