什么是跨域请求?
这一点不用我说了吧,想必看这篇文章的您正深刻体会着,心情估计是这样的,接下来估计是这样的,看完这篇文章预祝您是这样的(请原谅我的调皮)。
CORS(Cross Origin Resource Sharing)是如何工作的?
CORS 是通过向跨域请求的 Rquest、Response 添加HTTP Header来实现的 -- 客户端需要标明来源(
Origin),服务端反馈是否接受这个来源(
Access-Control-Allow-Origin)。但是有个大前提是,服务端必须支持CORS!
简单请求
对于简单的跨域请求(即 GETs,POSTs,而且没有设置头部,请求体也是 plain text 或者 form data),浏览器就会给头部加上额外加上Origin 来标明来源, 如下就是一个简单的跨域请求(我在http://jquery.com/ 站点的console 下执行的):
$.ajax({ url : 'http://localhost/corstest/index',success:function (data) { console.log(data) } });Request Header:
Origin:http://jquery.com
Error:
XMLHttpRequest cannot load http://localhost/corstest/index.
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://jquery.com' is therefore not allowed access.
原因是服务器的Response没有返回
'Access-Control-Allow-Origin'头部来表明这个请求是被允许的
public class IndexController : Controller { public string Index() { Response.AddHeader("Access-Control-Allow-Origin","http://jquery.com"); return "Hello World"; } }
从新请求,一切OK!
Response Header:
Access-Control-Allow-Origin:http://jquery.com
预飞请求(Preflighted Requests)
当有下列情况的时候,浏览器会发送预飞请求
- 使用除GET、POST 、HEAD外的 HTTP Method
- 有自定义头部
- Content-Type使用除 text/plain,application/x-www-form-urlencoded,或者 multipart/form-data外的类型,比如 application/json
例如执行如下请求(仍然是在http://jquery.com/ 站点的console 下执行):
$.ajax({ url : 'http://localhost/corstest/index',headers: {'From':'elvin'},//这里自定义了一个 From header success:function (data) { console.log(data) } });Request Header:
Request URL:http://localhost/corstest/index
Request Method:OPTIONS
...
Access-Control-Request-Headers:accept,from
Access-Control-Request-Method:GET
Origin:http://jquery.com
Request Method:OPTIONS
...
Access-Control-Request-Headers:accept,from
Access-Control-Request-Method:GET
Origin:http://jquery.com
Error:
XMLHttpRequest cannot load http://localhost/corstest/index.
Request header field From is not allowed by Access-Control-Allow-Headers.
需要注意的是 Request Method 是 OPTIONS,就是那个“预飞”, 这个请求是浏览器自动发出的!
报错的意思是说,服务端没有返回
Access-Control-Allow-Header来标明这个自定义header 是允许的。
下面我们调整下我们的服务端代码:
public class IndexController : Controller { public string Index() { Response.AddHeader("Access-Control-Allow-Origin","*"); if (Request.HttpMethod == "OPTIONS") { Response.AddHeader("Access-Control-Allow-Headers","From"); Response.End(); } return "Hello World"; } }
然后再次请求,一切OK!
Response Header:
Access-Control-Allow-Headers:From
Access-Control-Allow-Origin:*
相关阅读: