内容简介:举例:不进行预检请求的http请求,称为简单请求;如下是一个需要执行预检请求的 HTTP 请求:
- 不允许跨域的基本原因是:http请求头中没有允许跨域有关的参数。解决跨域请求的原理就是在拦截器中拦截请求,请在Http请求头添加允许跨域的字段
jspnp 跨域请求
- jsonp的缺点就是只能采用get请求。
- 为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许
- 基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
$.ajax({ url: 'http://localhost:1112/getPerson?callback=?', dataType: 'jsonp', jsonpCallback: 'person', success: function(data){ $('.name').html(data.name); $('.company').html(data.company); } }) 复制代码
cors(cross-origin-resource-share) 跨域资源共享:
cors机制:
- 它使用额外的HTTP头来告诉浏览器,让运行在一个origin上的web应用被准许访问来自不同源服务器上的指定资源。
- 当一个资源从与该资源本身所在的服务器不同的域/协议/端口请求一个资源的时候,资源会发起一个跨域请求;
举例:
- 站点http://domain-a.com 的某html页面通过src 请求http://domain-b.com/imge.jpg;
- 网络上的许多页面加载来自不同域的css样式表/图像/和脚本等资源;
处于安全原因:
- 浏览器限制从脚本内发起http跨域请求,或者是跨站请求可以正常发起,但是返回结果被浏览器拦截了 例如:XMLHttpRequest 和 fetch发起的请求;
- cors机制,允许web应用服务器进行跨域访问控制,从而是的跨域访问数据传输得以安全进行;
API遵循同源策略:
- 这意味着使用这些API的Web应用程序,只能从加载应用程序的同一个域请求HTTP资源, 除非 响应报文包含了正确CORS响应头。
新增CORS标准:
- 跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源;
- 对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。
cors举例:
比如说,假如站点 http://foo.example 的网页应用想要访问 http://bar.other 的资源。http://foo.example 的网页中可能包含类似于下面的 JavaScript 代码: var invocation = new XMLHttpRequest(); var url = 'http://bar.other/resources/public-data/'; function callOtherDomain() { if(invocation) { invocation.open('GET', url, true); invocation.onreadystatechange = handler; invocation.send(); } } 复制代码
简单请求:
不进行预检请求的http请求,称为简单请求;
Request: GET /resources/public-data/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Referer: http://foo.example/examples/access-control/simpleXSInvocation.html Origin: http://foo.example Response: HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2.0.61 Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml [XML Data] 复制代码
预检请求:
- “需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。
- "预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
预检请求条件:
1.使用了下面任一 HTTP 方法: PUT DELETE CONNECT OPTIONS TRACE PATCH 2.人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为: Accept Accept-Language Content-Language Content-Type (需要注意额外的限制) DPR Downlink Save-Data Viewport-Width Width 3.Content-Type 的值不属于下列之一: application/x-www-form-urlencoded multipart/form-data text/plain 4.请求中的XMLHttpRequestUpload 对象注册了任意多个事件监听器。 5.请求中使用了ReadableStream对象。 复制代码
如下是一个需要执行预检请求的 HTTP 请求:
var invocation = new XMLHttpRequest(); var url = 'http://bar.other/resources/post-here/'; var body = '<?xml version="1.0"?><person><name>Arun</name></person>'; function callOtherDomain(){ if(invocation) { invocation.open('POST', url, true); invocation.setRequestHeader('X-PINGOTHER', 'pingpong'); invocation.setRequestHeader('Content-Type', 'application/xml'); invocation.onreadystatechange = handler; invocation.send(body); } } ...... 复制代码
Request: 1.OPTIONS /resources/post-here/ HTTP/1.1 2.Host: bar.other 3.User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre 4.Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 5.Accept-Language: en-us,en;q=0.5 6.Accept-Encoding: gzip,deflate 7.Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 8.Connection: keep-alive 9.Origin: http://foo.example 10.Access-Control-Request-Method: POST 11.Access-Control-Request-Headers: X-PINGOTHER, Content-Type Response: 14.HTTP/1.1 200 OK 15.Date: Mon, 01 Dec 2008 01:15:39 GMT 16.Server: Apache/2.0.61 (Unix) 17.Access-Control-Allow-Origin: http://foo.example 18.Access-Control-Allow-Methods: POST, GET, OPTIONS 19.Access-Control-Allow-Headers: X-PINGOTHER, Content-Type 20.Access-Control-Max-Age: 86400 21.Vary: Accept-Encoding, Origin 22.Content-Encoding: gzip 23.Content-Length: 0 24.Keep-Alive: timeout=2, max=100 25.Connection: Keep-Alive 26.Content-Type: text/plain 复制代码
预检请求完成之后,发送实际请求:
POST /resources/post-here/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive X-PINGOTHER: pingpong Content-Type: text/xml; charset=UTF-8 Referer: http://foo.example/examples/preflightInvocation.html Content-Length: 55 Origin: http://foo.example Pragma: no-cache Cache-Control: no-cache <?xml version="1.0"?><person><name>Arun</name></person> HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://foo.example Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some GZIP'd payload] 首部字段 Access-Control-Max-Age 表明该响应的有效时间为 86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求 复制代码
附带身份凭证的请求:
Fetch 与 CORS 的一个有趣的特性是,可以基于 HTTP cookies 和 HTTP 认证信息发送身份凭证。一般而言,对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位。
本例中,foo.example 的某脚本向bar.other 发起一个GET 请求,并设置 Cookies:
var invocation = new XMLHttpRequest(); var url = ' bar.other/resources/c… ';
function callOtherDomain(){ if(invocation) { invocation.open('GET', url, true); invocation.withCredentials = true; invocation.onreadystatechange = handler; invocation.send();
} }
- withCredentials 标志设置为 true,从而向服务器发送 Cookies
- 因为这是一个简单 GET 请求,所以浏览器不会对其发起“预检请求”。但是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true ,浏览器将不会把响应内容返回给请求的发送者。
附带身份凭证的请求与通配符
- 附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“*”。
这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为foo.example,则请求将成功执行。
HTTP 响应首部字段
Access-Control-Allow-Origin
响应首部中可以携带一个 Access-Control-Allow-Origin 字段,其语法如下:
Access-Control-Allow-Origin: <origin> | * 复制代码
其中:
- origin 参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。
例如,下面的字段值将允许来自mozilla.com 的请求:
Access-Control-Allow-Origin: http://mozilla.com 复制代码
如果服务端指定了具体的域名而非“*”,那么响应首部中的 Vary 字段的值必须包含 Origin。这将告诉客户端:服务器对不同的源站返回不同的内容。
Access-Control-Allow-Credentials
- Access-Control-Allow-Credentials头指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容。
- 当用在对preflight预检测请求的响应中时,它指定了实际的请求是否可以使用credentials。请注意:简单 GET 请求不会被预检;如果对此类请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页。
Access-Control-Allow-Credentials: true 复制代码
HTTP 请求首部字段
Origin
Origin 首部字段表明预检请求或实际请求的源站。
Origin: <origin> 复制代码
origin 参数的值为源站 URI。它不包含任何路径信息,只是服务器名称。
Access-Control-Request-Headers
Access-Control-Request-Headers 首部字段用于预检请求。其作用是,将实际请求所携带的首部字段告诉服务器。
Access-Control-Request-Headers: <field-name>[, <field-name>]* 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Erupt 1.6.8 发布,注解级后台框架,零前端代码,非代码生成器,支持所有主流数据库
- 主流排序算法全面解析
- 推荐系统主流召回方法综述
- 主流超融合厂商技术对比
- 区块链三大主流技术简单梳理
- 3 个主流 Java 微服务框架
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Design for Hackers
David Kadavy / Wiley / 2011-10-18 / USD 39.99
Discover the techniques behind beautiful design?by deconstructing designs to understand them The term ?hacker? has been redefined to consist of anyone who has an insatiable curiosity as to how thin......一起来看看 《Design for Hackers》 这本书的介绍吧!