.Net Core Web API遇Origin为null的CORS跨域500错误求助
问题描述
当我从本地手动打开的HTML页面(Origin为null)向IIS Express上的Web API发送POST请求时,偶尔会遇到这个错误:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 500.
我的jQuery请求代码:
$.ajax({ headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, type: "POST", url: "http://localhost:12345/api/xs/" + selectedId, data: JSON.stringify(anyObj), dataType: "json" });
Web API控制器代码:
[Route("api/[controller]")] public class XSController : Controller { [HttpPost("{id}")] [EnableCors("AllowAll")] //[DisableCors()] public async Task<IActionResult> Post(ushort id, [FromBody]AnyObjVM model) { // 控制器逻辑 } }
Startup.cs的CORS配置:
public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddPolicy("AllowAll", builder => { builder.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials() ; }); }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseDefaultFiles(); app.UseStaticFiles(); app.UseCors("AllowAll"); app.UseMvc(); }
请求头信息:
Accept: application/json Accept-Encoding: gzip, deflate, br Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7 Connection: keep-alive Content-Length: 166 Content-Type: application/json Host: localhost:12345 Origin: null User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
我试过在Startup和控制器上开关CORS,也用--disable-web-security启动Chrome,但偶尔还是会触发这个问题,求解决办法!
解决方案分析
首先得重点关注错误里的HTTP 500状态码——很多时候CORS头缺失只是表象,真正的问题是API内部抛出了异常,导致CORS中间件根本没机会把响应头发送出去。咱们一步步来:
1. 先揪出API的500错误根源
你已经在开发环境开启了app.UseDeveloperExceptionPage(),那重现问题的时候,直接看API返回的详细错误信息就行。或者给控制器的Post方法加个断点/日志,检查这几个点:
id参数是否正确传递?比如selectedId是不是合法的ushort类型?AnyObjVM模型绑定有没有失败?比如你前端传的JSON结构和后端模型不匹配,[FromBody]绑定失败会直接抛出500错误。
一旦API抛出未处理异常,响应会直接返回500,这时候CORS中间件还没来得及加Access-Control-Allow-Origin头,浏览器就先报CORS错误,把真正的问题给掩盖了。
2. 专门处理Origin为null的特殊情况
本地file://协议打开的页面,Origin就是null,而你当前的CORS配置里AllowAnyOrigin()和AllowCredentials()一起用有个坑:
当启用AllowCredentials()时,浏览器不允许Access-Control-Allow-Origin设为*(AllowAnyOrigin()的效果)。针对null这个特殊Origin,你得显式允许它:
修改Startup里的CORS策略:
options.AddPolicy("AllowAll", builder => { builder.WithOrigins("null") // 显式允许Origin null .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); });
如果你不需要传递凭证(比如没有Cookie、HTTP认证信息),那直接去掉AllowCredentials()就行,这样AllowAnyOrigin()就能正常覆盖null的情况了。
3. 确认CORS中间件的顺序没搞错
你现在Configure方法里的顺序是对的:UseCors必须放在UseMvc之前,这样CORS头才能被正确添加到所有MVC的响应里。但要注意别让其他中间件(比如自定义的异常处理中间件)在UseCors之前就把响应返回了,那样CORS头也加不上。
4. 关于Chrome的--disable-web-security
这个参数单独用有时候不生效,得搭配--user-data-dir指定一个新的用户目录才行,比如:
chrome.exe --disable-web-security --user-data-dir="C:/TempChromeSession"
不过这只是临时调试用的,不能当正式解决方案。
5. 彻底解决的办法:别用file://协议
把你的本地页面放到一个Web服务器里,比如IIS Express(和API一起)、Node的http-server、Python的SimpleHTTPServer都行。这样页面的Origin就会是http://localhost:xxxx,和API的Origin一致,直接避开CORS问题。比如把HTML页面放到API项目的wwwroot目录下,用http://localhost:12345/yourpage.html访问,就不会有Origin null的麻烦了。
内容的提问来源于stack exchange,提问作者ael

