广安门外网站建设,403网站打开免费,品牌设计就是vi设计吗,广东微信网站制作公司哪家好文章目录同源策略cors基本概念cors跨域方式简单请求 simple request非简单请求- 预检请求CORS兼容情况CORS总结同源策略
在以前的一篇博客中有介绍#xff0c;同源策略是一种安全机制#xff0c;为了预防某些恶意的行为#xff0c;限制浏览器从不同源文档和脚本进行交互的行…
文章目录同源策略cors基本概念cors跨域方式简单请求 simple request非简单请求- 预检请求CORS兼容情况CORS总结同源策略
在以前的一篇博客中有介绍同源策略是一种安全机制为了预防某些恶意的行为限制浏览器从不同源文档和脚本进行交互的行为。
端口、协议、域名有一个不相同就是跨域。
要求同源的操作有 ajaxcookielocalStorageindexDB和dom操作
cors就是解决跨域的一种方式
cors基本概念
基本思想就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通从而决定请求或响应是应该成功或是失败。 从实现上来说cors不需要前端进行操作主要由服务端进行配置。 需要浏览器和服务器同时支持目前浏览器基本上都支持IE不能低于IE10
cors跨域方式
简单请求 simple request
请求方式如下
getposthead
http请求头信息为以下字段
AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type text/plainapplication/x-www-form-urlencodedmutipart/form-data
对于简单请求就是由浏览器直接发出的cors请求具体地讲就是在http头部中增加一个origin字段 例
GET /cors HTTP/1.1
Origin: http://m.xin.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...如上面所示origin字段用来说明本次的请求来自哪个源协议域名端口服务器根据这个值来判断是否同意该次请求。
如果origin指定的源不在服务器许可范围内服务器会返回一个正常的http响应浏览器发现这个回应的头信息没有包含Access-Control-Allow-Origin字段详见下文就知道出错了从而抛出一个错误被XMLHttpRequest的onerror回调函数捕获。注意这种错误无法通过状态码识别因为HTTP回应的状态码有可能是200。
如果origin指定的源在服务器许可范围内则服务器返回的响应头里会多出以下头信息字段
Access-Control-Allow-Origin: http://api.bob.com //必须
Access-Control-Allow-Credentials: true //可选
Access-Control-Expose-Headers: FooBar //可选
Content-Type: text/html; charsetutf-8Access-Control-Allow-Origin 这个字段是必须会有的他的值要么是请求是origin的值要么是*表示接受任意域名的请求。Access-Control-Allow-Credentials 该字段可选值为布尔值表示是否允许发送cookie。 默认情况下Cookie不包括在CORS请求之中。设为true即表示服务器明确许可Cookie可以包含在请求中一起发给服务器。这个值也只能设为true如果服务器不要浏览器发送Cookie删除该字段即可。ccess-Control-Expose-Headers 该字段可选。CORS请求时XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段就必须在Access-Control-Expose-Headers里面指定。上面的例子指定getResponseHeader(FooBar)可以返回FooBar字段的值。
注意 withCredentials 属性 CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器一方面要服务器同意指定Access-Control-Allow-Credentials字段为true。 另一方面需要开发者在Ajax请求中打开withCredentials 属性
var xhr new XMLHttpRequest();
xhr.withCredentials true;否则即使服务器发送cookie浏览器也不会发送或者服务器要求设置cookie浏览器也不会处理。
但是如果省略withCredentials设置有的浏览器还是会一起发送Cookie。这时可以显式关闭withCredentials。通过以下操作
xhr.withCredentials false;需要注意的是如果要发送CookieAccess-Control-Allow-Origin就不能设为星号必须指定明确的、与请求网页一致的域名。 同时Cookie依然遵循同源政策只有用服务器域名设置的Cookie才会上传其他域名的Cookie并不会上传且跨源原网页代码中的document.cookie也无法读取服务器域名下的Cookie。
简单请求代码参考 简单请求客户端不需要做什么处理这里只展示服务端需要做的处理。 服务端代码使用Node koa编写
ctx.set(Access-Control-Allow-Origin, http://localhost:3000);ctx.set(Access-Control-Allow-Credentials,true);body.data{carId:100,carName:宝马x5-1000};非简单请求- 预检请求
非简单请求是对服务器有特殊要求的请求。
请求方法
putdelete
Content-Type为application/json
非简单请求的CORS请求会在正式通信之前增加一次HTTP查询请求称为预检请求preflight。
浏览器先询问服务器当前网页所在的域名是否在服务器的许可名单之中以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复浏览器才会发出正式的XMLHttpRequest请求否则就报错。
例
var url http://api.uxin.com/user;
var xhr new XMLHttpRequest();
xhr.open(PUT, url, true);
xhr.setRequestHeader(X-Custom-Header, value);
xhr.send();上面代码中HTTP请求的方法是PUT并且发送一个自定义头信息X-Custom-Header。
浏览器发现这是一个非简单请求就自动发出一个预检请求要求服务器确认可以这样请求。下面是这个预检请求的HTTP头信息。
OPTIONS /cors HTTP/1.1
Origin: http://m.a.com
Access-Control-Request-Method: PUT //必有
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...预检请求用的请求方法是OPTIONS表示这个请求是用来询问的。头信息里面关键字段是Origin表示请求来自哪个源。
除了Origin字段预检请求的头信息包括两个特殊字段。
Access-Control-Request-Method
该字段是必须的用来列出浏览器的CORS请求会用到哪些HTTP方法上例是PUT。
Access-Control-Request-Headers
该字段是一个逗号分隔的字符串指定浏览器CORS请求会额外发送的头信息字段上例是X-Custom-Header。
CORS预检请求的响应 服务器收到预检请求以后检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后确认允许跨源请求就可以做出回应。 例
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://m.a.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charsetutf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout2, max100
Connection: Keep-Alive
Content-Type: text/plain上面的HTTP回应中关键的是Access-Control-Allow-Origin字段该字段简单请求也是必有的表示http://m.a.com可以请求数据。该字段也可以设为星号表示同意任意跨源请求。
如果浏览器否定了预检请求会返回一个正常的HTTP回应但是没有任何CORS相关的头信息字段。这时浏览器就会认定服务器不同意预检请求因此触发一个错误被XMLHttpRequest对象的onerror回调函数捕获。控制台会打印出如下的报错信息。
XMLHttpRequest cannot load http://m.a.com.
Origin http://m.a.com is not allowed by Access-Control-Allow-Origin.服务器也可以回应的其他CORS相关字段如下。
Access-Control-Allow-Methods: GET, POST, PUT //必有
Access-Control-Allow-Headers: X-Custom-Header //必有
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000 //可选Access-Control-Allow-Methods
该字段必需它的值是逗号分隔的一个字符串表明服务器支持的所有跨域请求的方法。注意返回的是所有支持的方法而不单是浏览器请求的那个方法。这是为了避免多次预检请求。
2Access-Control-Allow-Headers
如果浏览器请求包括Access-Control-Request-Headers字段则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串表明服务器支持的所有头信息字段不限于浏览器在预检中请求的字段。
3Access-Control-Allow-Credentials
该字段与简单请求时的含义相同。
4Access-Control-Max-Age
该字段可选用来指定本次预检请求的有效期单位为秒。上面结果中有效期是20天1728000秒即允许缓存该条回应1728000秒即20天在此期间不用发出另一条预检请求。
当服务器通过了预检请求时以后的每次浏览器cors请求都跟简单请求一样会有一个Origin头信息字段。服务器的回应也都会有一个Access-Control-Allow-Origin头信息字段。
下面是预检请求之后浏览器的正常CORS请求。
PUT /cors HTTP/1.1
Origin: http://m.a.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0..上面头信息的Origin字段是浏览器自动添加的。
下面是服务器正常的回应。
Access-Control-Allow-Origin: http://m.a.com
Content-Type: text/html; charsetutf-8上面头信息中Access-Control-Allow-Origin字段是每次回应都必定包含的。
cors 预检请求服务端代码 //OPTIONS 请求查询服务器的性能或者查询与资源相关的选项和需求ctx.set(Access-Control-Allow-Credentials, true);ctx.set(Access-Control-Allow-Methods,PUT);ctx.set(Access-Control-Allow-Origin, http://localhost:3000);ctx.set(Access-Control-Allow-Headers, content-type);ctx.set(Access-Control-Max-Age,100);body.data {carId: 100,carName: 宝马x5}CORS兼容情况
CORS支持IE10IE89需要使用IE独有的api - 使用XDomainRequest对象来支持 cors。
注意ie下 localhost:8000localhost:8001localhost 视为同域以免本地进行测试的时候踩坑。
CORS总结
我们要知道CORS是http协议的一部分由浏览器和服务器来完成。所以对于前端来说还是比较简单的。我们要做的是理解这个协议和实现机制在遇到类似问题的时候可以快速的定位。
参考文章https://www.cnblogs.com/zhaojiu/p/14452493.html