前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >跨域解决方案介绍2,转自github.

跨域解决方案介绍2,转自github.

作者头像
杭州前端工程师
发布2018-06-15 12:01:49
7910
发布2018-06-15 12:01:49
举报
文章被收录于专栏:前端大白专栏前端大白专栏
跨域问题

浏览器的安全基石是“同源政策”,所谓同源是指协议相同,域名相同,端口相同,只要其中有一个不同,则称为不同源。不同源的网站之间不能够相互请求数据,以确保用户数据的安全性。 但有的时候,一个网站不得不请求别的域上面的数据,这个过程就称为跨域。

跨域的实现方法有以下几种:

(1)JSONP

JSONP(JSON with padding)的原理是script标签不受同源安全策略限制,它可以向别的域发送get请求。

代码语言:javascript
复制
function handleResponse(data) {
	console.log('The response data is:' + data);
}
//动态添加script标签
var script = document.createElement('script');
script.src = 'http://www.baidu.com/json?callback=handleResponse';
script.setAttribute('type', 'text/javascript');
document.body.appendChild(script);

后台收到get请求后,根据callback参数生成相应的JSONP数据 handleResponse({'data': serverdata}),这段数据返回前端就会被当作js代码执行,触发回调函数。

jQuery和JSONP

代码语言:javascript
复制
$(document).ready(function(){
	$.ajax({
		type: 'get',
		async: false,
		// 查询CA1998次航班的信息
		url: 'http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998',
		dataType: 'jsonp',
		//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
		jsonp: 'callback',
		//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
		jsonpCallback: 'flightHandler',
		success: (json) => {
			alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
		},
		error: () => {
			alert('fail');
		}
	});
});
(2)CORS

CORS是一个W3C标准,全称为跨域资源共享(cross-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

整个CORS通信过程都由浏览器自动完成,用户不需要参与,对于前端开发者来说,同源ajax和CORS的代码完全相同,因此,实现CORS的关键在于服务器是否提供CORS接口。

简单请求例子:

代码语言:javascript
复制
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

若服务器允许来自http://api.bob.com的跨域请求,则会进行如下响应:

代码语言:javascript
复制
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true  //是否允许发送cookie
Access-Control-Expose-Headers: FooBar  // 额外的header字段
Content-Type: text/html; charset=utf-8

若不允许,则不会设置Access-Control-Allow-Origin字段,如果服务器将此字段设为*,则表示服务器接受所有域的跨域请求。

Access-Control-Allow-Credentials: true 则表明服务器接受cookie,同时开发者应在AJAX打开withCredentials属性,以允许浏览器发送cookie:

代码语言:javascript
复制
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

跨域资源共享 CORS 详解

(3)iframe + HTML5 postMessage

即不同window间通过HTML5的API postMessage进行跨域通信,其格式为:

代码语言:javascript
复制
otherWindow.postMessage(data, targetOrigin);
// otherWindow指要接收消息的窗口,targetOrigin限制接收窗口所在的域,若不想限制,设为*即可

示例:

代码语言:javascript
复制
<!--a.com/index.html-->
<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
    var ifr = document.getElementById('ifr');
    var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样
                                        // 若写成'http://c.com'就不会执行postMessage了
    ifr.contentWindow.postMessage('Message from a.com!', targetOrigin);
};
</script>
代码语言:javascript
复制
<!--b.com/index.html-->
<script type="text/javascript">
    window.addEventListener('message', function(event){
        // 通过origin属性判断消息来源地址
        if (event.origin == 'http://a.com') {
            alert(event.data);    // 弹出"Message from a.com!"
            alert(event.source);  // 对a.com、index.html中window对象的引用
                                  // 但由于同源策略,这里event.source不可以访问window对象
        }
    }, false);
</script>
(4)iframe + window.name

原理: windoe.name 的值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)

a.com/1.html

代码语言:javascript
复制
<script type="text/javascript">
function getData() {
	var ifr = document.getElementById('proxy');
	ifr.src = 'a.com/2.html'; //跳转到同源网站
	ifr.onLoad = function() {
		var data = ifr.contentWindow.name;
		alert(data);
	}
}
</script>
<iframe src='http://other-origin/data.html' style='display:none' onLoad='getData()'></iframe>

other-origin/data.html

代码语言:javascript
复制
var data = {
	name: 'xiaoming',
	age: 12
};
window.name = JSON.stringify(data);
(5)WebSocket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

代码语言:javascript
复制
请求头信息:(多了个 origin)
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

响应头:(如果origin在白名单内)
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 跨域问题
  • (1)JSONP
  • (2)CORS
  • (3)iframe + HTML5 postMessage
  • (4)iframe + window.name
  • (5)WebSocket
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档