IT忍者神龟之什么叫跨域访问

xiaoxiao2021-02-28  47

1.什么是跨域访问 JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。 首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表: URL 说明 是否允许通信 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同协议 不允许 http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名对应ip 不允许 http://www.a.com/a.js http://script.a.com/b.js 主域相同,子域不同 不允许 http://www.a.com/a.js http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问) http://www.cnblogs.com/a.js http://www.a.com/b.js 不同域名 不允许

跨域的解决方案: 1.jsonp比较常用 2.CORS(Cross-Origin Resource Sharing) JOSNP解决方案: 就是利用<script>标签没有跨域限制来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,形如: <script src=”http://www.example.net/api?param1=1¶m2=2″></script> 并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。 第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如: callback({“name”:”hax”,”gender”:”Male”}) 这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。 跨域访问: 地址:http://p.3.cn/prices/mgets?skuIds=J_2146845&type=1&callback=setPrice 回调:setPrice 数据格式:[{"id":"J_2146845","p":"139.00","m":"159.00"}] html代码: <button id="btn">按钮</button> <div id="div"></div> js代码: var div = document. getElementById("div"); var oScript = null; var btn = document.getElementById("btn").onclick = function () { //伪造一个script加载过程 oScript = document.createElement("script"); oScript.src = "http://p.3.cn/prices/mgets?skuIds=J_2325379&type=1&callback=setPrice"; document.body.appendChild(oScript); }; function setPrice(str){ div.innerHTML = str[0].p; console.log(str[0].m); document.body.removeChild(oScript); }

cors解决方案:

这是一个W3C标准(显然比jsonp背景深厚许多),同样需要浏览器和服务器同时支持,但是整个通信过程,都是浏览器自动完成,不需要用户参与,就像平时写Ajax一样(如果使用的是jquery的话)。下面是原生js实现CORS的代码

function createCORSRequest(method,url){ var xhr=new XMLHttpRequest(); if("withCredentials" in xhr){ xhr.open(method,url,true); }else if(typeof XDomainRequest != "undefined"){//IE10之前的版本使用XDmainRequest支持CORS xhr=new XDomainRequest(); xhr.open(method,url); }else{ xhr=null; } return xhr; } var request=createCORSRequest("get","待访问的地址"); if(request){ request.onload=function(data){ //do sth }; request.send(); }

适用场景:

承载的信息量大,get形式搞不定,需选用post传输。CORS支持所有类型的传输。

兼容性:

移动端全面支持(除opera mini),PC上IE8+。

CORS思想:

使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。(请求和响应都不包含cookie)

当然如果设置成下面这样,所有的跨域都可以实现了,但这样毕竟太不安全。“Access-Control-Allow-Origin:*”;//允许任何域向我们的服务器发送请求

一般情况下,浏览器发送一个额外的Origin头部(由浏览器自动生成发送) Origin:http://localhost:8080//本地网址

然后由服务器发送一个响应表头:Access-Control-Allow-Origin,如果服务器接收该请求,返回值(只能是通配符或单域名。)就和请求值一样。

Access-Control-Allow-Origin:http://localhost:8080

=>CORS方案的重点其实就在于服务器端的配置。

简单请求

只使用 GET, HEAD 或者 POST 请求方法。如果使用 POST 向服务器端传送数据,则数据类型(Content-Type)只能是 application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种。不会使用自定义请求头(类似于 X-Modified 这种)。HTTP头部信息不超出以下{Accept,Accept-Language,Content-Language,Last-Event-ID,content-type(只限于上面提到的3种类型)}

对于简单请求,浏览器直接发出CORS请求。浏览器会自动在头信息(Request Headers)中,添加一个Origin 字段,来表明本次请求来自哪个域。

Paste_Image.png

如果这个源不在许可范围内,会报错: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

如果Origin指定的域名在许可范围内(必须是跨域了的),Response Headers中会多出几个头信息字段。

Access-Control-Allow-Credentials:true//值为true表示允许发送cookie Access-Control-Allow-Methods:GET, POST, OPTIONS Access-Control-Allow-Origin:http://localhost:8080 Access-Control-Max-Age:1728000
withCredentials属性

因为CORS默认不发送cookie和http认证,如果要把Cookie发到服务器,就要指定Access-Control-Allow-Credentials:true;另外AJAX中也要打开withCredentials属性。

var xhr=new XMLHttpRequest(); xhr.withCredentials=true;

jquery ajax请求参数中加入

xhrFields: { withCredentials: true }

非简单请求

除了上面说的简单请求外都是非简单请求,比如:请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,又或者有自定义请求头Access-Control-Request-Headers: X-Custom-Header。

比如,我添加自定义请求头

xhr.setRequestHeader('Some-Custom-Response-Header', 'value');

就会发现连续向同一地址请求了两次,而第一次请求什么值也没拿到

Paste_Image.png

第二次请求

Paste_Image.png

这是因为浏览器发现,这是一个非简单请求,就自动发出一个”预检”请求,要求服务器确认可以这样请求。”预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的。”预检”请求之后,浏览器球会进行正常CORS请求。

服务器端配置(rails为例)

1、可以参考这个方法:为 RESTful API 配置 CORS 实现跨域请求,写的挺详细的。然而对于rails并不算熟悉的我来说,有gem包,怎么可能放着不用呢~2、这是Rack CORS 中间件的项目地址,按照文档的说明1分钟就可以基本搞

转载请注明原文地址: https://www.6miu.com/read-2626138.html

最新回复(0)