stackoverflow.com/questions/1…
Access-Control-Allow-Origin 基本在开发初期,一个人在刚开始学习前后端分离,一定会碰到这个问题,第一反应就是跨域。
Question
- 一个客户从 http://siteA 下载 JS 代码 MyCode.js。
- MyCode.js 的响应头包含 Access-Control-Allow-Origin:http://siteB,我认为 MyCode.js 被允许对网站 B 进行跨源引用。
- 客户端触发了 MyCode.js 的一些功能,这些功能又向 http://siteB ,尽管是跨源请求,但应该没有问题。
但是我错了,她根本不是这样工作的。
我对网站 A 和网站 B 都有完全的控制权,我怎么样才能让网站 A 下载的 JS 代码使用这个标头来访问网站 B 的资源呢?我不想使用 JSONP。
Answer
Access-Control-Allow-Origin 是一个 CORS「跨资源共享」 标头。
当网站 A 试图从网站 B 获取内容时,网站 B 可以发送一个 Access-Control-Allow-Origin 响应头,告诉浏览器这个页面的内容可以被某些来源访问。默认情况下,网站 B 的页面不能被任何其他来源访问;使用 Access-Control-Allow-Origin 头为特定请求来源的跨源访问打开了大门。
对于网站 B 想让网站 A 访问的每个资源/页面,网站 B 应该用响应头来提供其页面:
Access-Control-Allow-Origin: siteA.com
现代浏览器不会直接阻止跨域请求。如果网站 A 从网站 B 请求一个页面,浏览器将在网络层面上实际获取所请求的页面,并检查响应头是否将网站 A 列为允许的请求者域。如果 B 站点没有表明 A 站点被允许访问这个页面,浏览器将触发 XMLHttpRequest 的错误事件,并拒绝向请求的 JavaScript 代码发送响应数据。
Non-simple requests
在网络层面发生的事情可能比上面解释的要稍微复杂一些。如果是请求一个“非简单”的请求,浏览器首先发送一个无数据的“preflight”OPTIONS 请求,以验证服务器是否接收该请求。一个请求在以下情况是非简单的(或两者)。
- 使用 get 或 post 以外的 Http 动词(如 put、delete)。
- 使用非简单的请求头;唯一的简单请求头是:
-
-
Accept
-
Accept-Language
-
Content-Language
-
Content-Type (this is only simple when its value is application/x-www-form-urlencoded, multipart/form-data, or text/plain)
-
如果服务器用适当的响应头(非简单头的Access-Control-Allow-Headers,非简单动词的Access-Control-Allow-Methods)响应 OPTIONS 预检,与非简单动词和/或非简单头匹配,那么浏览器就会发送实际请求。
假设网站 A 想为 /somePage 发送一个 PUT 请求,其非简单的内容类型值为 application/json,浏览器将首先发送一个预检请求。
OPTIONS /somePage HTTP/1.1
Origin: siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type
注意,Access-Control-Request-Method和Access-Control-Request-Headers是由浏览器自动添加的,你不需要添加它们。这个OPTIONS预检得到了成功的响应头信息。
Access-Control-Allow-Origin: siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type
当发送实际请求时(在预检完成后),其行为与简单请求的处理方式相同。换句话说,一个预检成功的非简单请求的处理方式与简单请求相同(即,服务器仍然必须再次发送Access-Control-Allow-Origin以获得实际响应)。
浏览器发送实际请求:
PUT /somePage HTTP/1.1
Origin: siteA.com
Content-Type: application/json
{ "myRequestContent": "JSON is so great" }
而服务器会发回一个 Access-Control-Allow-Origin,就像它对一个简单的请求一样:
Access-Control-Allow-Origin: siteA.com
关于更多非简单请求的信息,请参看:stackoverflow.com/questions/1…