美文网首页
进阶13-常见的跨域解决方案

进阶13-常见的跨域解决方案

作者: 夜流光丶 | 来源:发表于2017-06-21 20:16 被阅读0次
  • 什么是同源策略

同源策略是指浏览器处于安全方面的考虑只允许本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读取对方的资源。
其中同源是指:
- 协议相同,比如http://lalala.comhttps://lalala.com不属于同源
- 域名相同,比如http://b.lalala.comhttp://a.lalala.com不属于同源
- 端口相同,比如http://lalala.com:8082http://lalala.com不属于同源

  • 什么是跨域?跨域有几种实现形式

跨域是指不同域之间的接口进行交互;
常见的跨域解决方式有如下几种:
- ### JSONP
JSONP是JSON with Padding的简写,是应用JSON的一种方法,JSONP看起来 与JSON差不多,只不过是被包含在回调函数中的JSON。JSONP由两部分组成,回调函数和JSON数据,回调函数是当响应到来时应该在页面中调用的函数(这个函数会在页面中提前定义好)。所以JSONP的原理是利用<script>标签可以不受限制地从其他域加载资源的能力动态创建<script>标签,然后在这个标签中向指定url请求JSONP数据,当数据被服务端传回页面时,回调函数把JSON数据传入并执行,从而达到从其他域直接访问响应文本的目的。例如:
//事件处理函数,当需要去访问其他域的文本时触发 function eventHandler() { var script = document.createElement('script'); script.src = 'http://otherDomain.com/json/?callback=JSONHandler' document.body.appendChild(script); } //回调函数,当服务端传回类似'JSONHandler' + '(' + json ')'的数据时调用 function JSONHandler(json) {}
下面是一个简单通过JSONP实现的猜数例子:
客户端代码:
<!doctype html> <html> <head> </head> <body> <div id='ctn'> <input type="input" id="number" placeholder="1到100的整数" > <br> <button id="guess">猜吧</button> </div> <script> function $(str) { return document.querySelector(str); } var input = $('#number'); var guess = $('#guess'); //事件处理函数 guess.addEventListener( 'click', function() { var guessNumber = parseInt(input.value); if(isNaN(guessNumber)) { alert('老铁,输个数字过来好吗');return;} var script = document.createElement('script'); script.src = 'http://localhost:8080/guessNumber?callback=xxx&number=' + guessNumber; document.body.appendChild(script); }) //回调函数 function xxx(json) { div = document.createElement('div'); div.innerText = '你猜的数字是:' + parseInt(input.value) + ',' + json[parseInt(input.value)]; ctn.appendChild(div); } </script> </body> </html>
服务端代码:
var theNumber = 77; app.get('/guessNumber', function(req, res){ var data = {}; var guessNumber = parseInt(req.query.number); if(guessNumber > theNumber) { data[guessNumber] = '大了'; } else if(guessNumber < theNumber) { data[guessNumber] = '小了'; } else { data[guessNumber] = '中了'; } //返回JSONP var cb = req.query.callback; console.log(cb); if(cb) { let tmp = cb + '('+ JSON.stringify(data) +')' console.log(tmp); res.send(tmp); } else { res.send(data); } })
下图为本地开启server-mock的效果图:

image.png
  • CROS

CROS(Cross-Origin Resource Sharing,跨域资源共享)是W3C定义的一个跨域资源共享规范,规定了在必须访问跨域西原始浏览器与服务器应该如何沟通。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

比如一个简单请求,它没有自定义头部,在发送之前需要给它附加一个额外的`Origin`头部,其中包含请求页面的源信息(协议、域名、端口),以便服务器根据这个头部信息来决定是否给予响应;如果服务器认为该请求可以接受,则在响应报文的首部中添加`Access-Control-Allow-Origin`的头,其值与请求报文中`Origin`头的值一致,或者为`*`表示接受所有域的请求。这里的`Origin`头的发送与是否跨域无关。
其中简单请求的定义如下:
>只要同时满足以下两大条件,就属于简单请求
1.  请求方法是以下三种方法之一:
    - HEAD
    - GET
    - POST
2. HTTP的头信息不超出以下几种字段:
    - Accept
    - Accept-Language
    - Content-Language
    - Last-Event-ID

其中Content-Type:只限于三个值application/x-www-form-urlencoded、 multipart/form-data、text/plain

若是一个非简单请求(相对简单请求而言),则在正式发送请求报文之前需要通过`OPTIONS`方法发送一个预检报文,报文首部有`Access-Control-request-method`头和`Access-Control-request-Headers`头,用以告知服务器实际请求所使用的HTTP方法和携带的自定义首部,然后服务器根据这些值判断是否接受该请求;然后返回响应报文,在响应报文中添加`Access-Control-Allow-Methods`头和`Access-Control-Allow-Headers`头作为请求报文中对应头的回复。
  • 降域

// 降域方式
// 修改document.domain的方法只适用于不同子域
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
    document.domain = 'example.com';//设置成主域
    function test(){
        alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
    }
</script>
// 子窗口
<script type="text/javascript">
    document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
</script>
  • postMessage

window.postMessage(message,targetOrigin)方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

调用`postMessage`方法的`window`对象是指要接收消息的那一个`window`对象,该方法的第一个参数`message`为要发送的消息,类型只能为字符串;第二个参数`targetOrigin`用来限定接收消息的那个`window`对象所在的域,如果不想限定域,可以使用通配符 *  。需要接收消息的`window`对象,可是通过监听自身的`message`事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

更多请参看:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
http://zqdevres.qiniucdn.com/data/20160412110843/index.html
http://www.cnblogs.com/2050/p/3191744.html

相关文章

  • 进阶13-常见的跨域解决方案

    什么是同源策略 同源策略是指浏览器处于安全方面的考虑只允许本域下的接口交互。不同源的客户端脚本在没有明确授权的情况...

  • 进阶13-跨域

    题目1: 什么是同源策略 浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情...

  • 跨域

    博客 说说跨域那些事儿 不要再问我跨域的问题了 前端常见跨域解决方案(全) 同源策略 JSONP(填充式JSON)...

  • 常见跨域解决方案

    目前常见的跨域解决方案 Jsonp最早的解决方案,利用script标签可以跨域的原理实现限制: 需要服务的支持 只...

  • 前端常见跨域解决方案(全)

    前端常见跨域解决方案(全) 什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的...

  • js常见跨域解决方案

    参考:前端常见跨域解决方案(全) 跨域,什么是“域”? 这里就要先说说同源策略了。所谓同源是指"协议+域名+端口"...

  • 前端不同的跨域方案总结

    做个收录,方便以后复盘。本文转自:前端常见跨域解决方案(全)。 什么是跨域? 跨域是指一个域下的文档或脚本试图去请...

  • JWT简介

    前言 JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。微服务常见的认证方案 一、跨域认证...

  • 常见跨域解决方案以及Ocelot 跨域配置

    常见跨域解决方案以及Ocelot 跨域配置 Intro 我们在使用前后端分离的模式进行开发的时候,如果前端项目和a...

  • JS知识点

    1、前端常见跨域解决方案 2、cookie,localStorage,SessionStorage三者的区别 3、...

网友评论

      本文标题:进阶13-常见的跨域解决方案

      本文链接:https://www.haomeiwen.com/subject/ewttcxtx.html