内容简介:举例:不进行预检请求的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 微服务框架
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入理解C#(第3版)
斯基特 (Jon Skeet) / 姚琪琳 / 人民邮电出版社 / 2014-4-1 / 99.00元
本书是世界顶级技术专家“十年磨一剑”的经典之作,在C#和.NET领域享有盛誉。与其他泛泛介绍C#的书籍不同,本书深度探究C#的特性,并结合技术发展,引领读者深入C#的时空。作者从语言设计的动机出发,介绍支持这些特性的核心概念。作者将新的语言特性放在C#语言发展的背景之上,用极富实际意义的示例,向读者展示编写代码和设计解决方案的最佳方式。同时作者将多年的C#开发经验与读者分享,读者可咀其精华、免走弯......一起来看看 《深入理解C#(第3版)》 这本书的介绍吧!