跨域方法整理

陈兔兔的前端日记 陈兔兔的前端日记     2022-08-12     728

关键词:

    在讲跨域前必须了解同源策略:同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当一个百度浏览器执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。简单的一句话就是:“如果两个页面拥有相同的协议(protocol),端口(如果指定),和主机,那么这两个页面就属于同一个源(origin)。”下图为是否同源:

  

为了保证用户信息的安全,防止恶意的网站窃取数据。同源策略下:Cookie、LocalStorage 和 IndexDB 无法读取,DOM 无法获得,AJAX 请求不能发送。(ps:如果想更多了解同源策略可以看阮一峰大神的博客:http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html)。

  为了解决不同源之间通讯,跨域因此而生:

    方法一:JSONP

                 jsonp:JSONP是json with padding的简称,jsonp看起来跟json差不多,只不过是包含在函数中的json数据而已。

callback({"name":"xiaotutu"});

 

 

 

因为script标签是不受同源策略影响的,它可以引入来自任何地方的js文件。而jsonp的原理就是,在客户端和服务端定义一个函数,当客户端发起一个请求时,服务端返回一段javascript代码,其中调用了在客户端定义的函数,并将相应的数据作为参数传入该函数。一般情况下,为了这个script标签能够动态的调用,我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。代码如下:

        

function jsonp_callback(data) {
    console.log(data);
}
function jsonpAjax(){
    var url = "http://a.com/b.php?jsonp_callback=jsonp_callback";
    var script = document.createElement('script');
    // 发送请求
    script.src = url;
    document.head.appendChild(script);
}
jsonpAjax()

 

当服务器接受到callback时候会返回相应的代码

 

 

jsonp_callback({
   "name": "chentutu"
});

 

jsonp是想对来说比较简单的,灵活的利用了<script>的不受限制从其它域加载资源。因为javascript是有效代码所以在请求完成后,就会被立即执行。

方法二:<img>

跟script一样能不受其它域限制加载资源,使用它们的onload和onerror事件处理程序来确定是否响应。但它只能用来发送GET请求,且无法获取服务端的响应文本,所以只能利用它实现一些简单的、单向的跨域通信,例如跟踪用户的点击。大家看看下面的例子:

var img = new Image();
img.onload = function(){
    console.log('done')
    img.onload = null;
    img = null;
}
img.src = "http://xx/xx.gif"

方法三:CORS

   CORS(Cross-Origin Resource Sharing,跨源资源共享)是W3C小组制定的一个标准,它允许浏览器实现跨域通信。通过建立一个XmlHttpRequest对象,CORS允许开发者象实现同源请求那样实现跨源请求。CORS(跨源资源共享)的实现目标非常简单。假设站点B想访问站点A中的某些数据,使用同源请求将不能满足这一需求。但是,通过CORS请求,站点A可以通过在部分页面中加入特殊的响应头的方法来允许站点B访问。

    注意CORS只支持以下浏览器:

  • Chrome 3以上版本的浏览器
  • Firefox 3.5以上版本的浏览器
  • Safari 4以上版本的浏览器
  • Internet Explorer 8以上版本的浏览器

下面就是一个创建请求对象的代码:

 function createCORSRequest(method, url) {
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr) {
        //检查XMLHttpRequest对象是否拥有一个withCredentials属性
        //withCredentials属性只属于XMLHTTPRequest2对象
        xhr.open(method, url, true);
    } 
    else if (typeof XDomainRequest != "undefined") {
        //否则,检查XDomainRequest对象 Otherwise, check if XDomainRequest.
        //XDomainRequest对象只存在于IE浏览器中,且被IE浏览器用来创建CORS请求
        xhr = new XDomainRequest();
        xhr.open(method, url);

    } 
    else {
        //否则,CORS不被当前浏览器支持
        xhr = null;
    }
    return xhr;
}

var xhr = createCORSRequest('GET', url);
if (!xhr) {
    throw new Error('CORS不被支持!');
}

在默认情况下,标准的CORS请求不发送或设置任何cookie。为了在请求中包含cookie,你需要将XmlHttpRequest对象的withCredentials属性值设为true。为了达到目的,服务器端必须将Access-Control-Allow-Credentials响应头设为true。.withCredentials属性值的设置将会使跨源请求中可以包含任何cookie,开发者也可以通过使用该属性值来跨源设置任何cookie。请注意,这些cookie也可以使用同源安全策略,即被跨源设置的cookie中的内容不能被同源的JavaScript脚本代码所访问,只能被设置这些cookie的源所访问。

一个使用CORS请求的完整代码示例如下所示:

//创建XHR对象
function createCORSRequest(method, url) {
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr) {
        //Chrome/Safari/Firefox浏览器中的XHR对象
        xhr.open(method, url, true);
    } 
    else if (typeof XDomainRequest != "undefined") {
        //在IE浏览器中创建XDomainRequest对象
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } 
    else {
        //CORS不被支持.
        xhr = null;
    }
    return xhr;
}
//从服务器端响应中获取title标签
function getTitle(text) {
    return text.match('')[1];
}
//创建CORS请求
function makeCorsRequest() {
    // bibliographica.org支持CORS请求
    var url = 'http://bibliographica.org/';

    var xhr = createCORSRequest('GET', url);
    if (!xhr) {
        alert('您的浏览器不支持跨源请求');
        return;
    }

    //处理服务器端响应
    xhr.onload = function() {
        var text = xhr.responseText;
        var title = getTitle(text);
        alert('来自' + url + '的响应: ' + title);
    };

    xhr.onerror = function() {
        alert('跨源请求失败!');
    };
    xhr.send();
}

CORS分为简单和非简单模式:详细请见阮一峰大神的博客:http://www.ruanyifeng.com/blog/2016/04/cors.html

        方法四:document.domain

  • 原理:相同主域名不同子域名下的页面,可以设置document.domain让它们同域
  • 限制:同域document提供的是页面间的互操作,需要载入iframe页面

以下是document.domain实际操作的代码:

var ifr = document.createElement('iframe');
ifr.src = 'http://b.a.com/bar'; 
ifr.onload = function(){
    var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
    ifrdoc.getElementsById("foo").innerHTML);
};

ifr.style.display = 'none';
document.body.appendChild(ifr);

注意:如果修改了document.domain,则在某些机器上的IE678里,获取location.href有权限异常。document.domain只能从子域设置到主域,往下设置以及往其他域名设置都是不允许的。

方法五:window.postMessage

 

  • 原理:HTML5允许窗口之间发送消息
  • 限制:浏览器需要支持HTML5,获取窗口句柄后才能相互通信
//发送端
var win = window.open('http://b.com/bar');
win.postMessage('Hello world!', 'http://b.com'); 

//接收端
window.addEventListener('message',function(event) {
    console.log(event.data);
});

想了解window.postMessage的博友可以看看张鑫旭老师的博客:http://www.zhangxinxu.com/wordpress/2012/02/html5-web-messaging-cross-document-messaging-channel-messaging/

方法六:WebSocket

WebSocket 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很棒的实现。(不用http协议有自己的一套协议)。

在客户端的实例:

var ws = new WebSocket('ws://127.0.0.1:8080/url'); //新建一个WebSocket对象,注意服务器端的协议必须为“ws://”或“wss://”,其中ws开头是普通的websocket连接,wss是安全的websocket连接,类似于https。
ws.onopen = function() {
    // 连接被打开时调用
};
ws.onerror = function(e) {
    // 在出现错误时调用,例如在连接断掉时
};
ws.onclose = function() {
    // 在连接被关闭时调用
};
ws.onmessage = function(msg) {
    // 在服务器端向客户端发送消息时调用
    // msg.data包含了消息
};
// 这里是如何给服务器端发送一些数据
ws.send('some data');
// 关闭套接口
ws.close();

详情大家还是看红宝书591吧。

    

 

前端面试题整理

...ceof用于判断一个变量是否属于某个对象的实例。2.什么是跨域?跨域请求资源的方法有哪些?由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。存在跨域的情况。跨域请求... 查看详情

前端工程师面试题?vue2知识整理?

...插槽是把子组件里的数据传到父组件的插槽里使用什么是跨域跨域是浏览器的跨域不符合域名协议端口号一样(同源策略)的请求都会出现跨域的问题跨域的解决方法最多的情况是后端处理跨域前端的跨域服务器代理jsonpvue中是p... 查看详情

关于springboot常见面试题整理笔记

...rtLists]3、[endif]@ComponentScan:组件扫描3、springboot中如何解决跨域问题跨域都是通过前端JSONP来解决,但只能处理get类型请求,像post、put、delete就不支持,所以一般采用后端跨域通过WebMvcConfiguration接口来重写addCorsMappings方法,解决... 查看详情

项目知识盲区整理4(代码片段)

...本编译器集合常用图表插件常用字体插件验证码elementjwt跨域--origin请求头非Controller层通过RequestContextHolder.getRequestAttributes()获取HttpServletRequest,HttpServletResponse拦截器HandlerInterceptorAdapter使用方法设置拦截器为f 查看详情

理解跨域及常用解决方案(代码片段)

跨域,相信大家无论是在工作中还是在面试中经常遇到这个问题,常常在网上看到别人所整理的一些方法,看似知道是怎么回事,但如果没有动手实践过,总觉得自己没有真正的掌握,在这里,通过自己认真思考整理一些常用的... 查看详情

jquery整理

$.extend扩展Jquery的bin绑定事件,unbind取消所有事件Jquery学习地址:http://www.runoob.com/jquery/jquery-plugin-validate.htmlJquery学习地址:http://www.haorooms.com/post/jquery_selecter_zj使用ajax的jsonP跨域请求数据,需要在服务器对数据进行处理ajax跨域 查看详情

关于springboot常见面试题整理笔记

...置功能3、@ComponentScan:组件扫描3、springboot中如何解决跨域问题跨域都是通过前端JSONP来解决,但只能处理get类型请求,像post、put、delete就不支持,所以一般采用后端跨域通过WebMvcConfiguration接口来重写addCorsMappings方... 查看详情

iframe跨域通信方案

参考技术A概述JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:首先什么是跨域,简单地理解就是... 查看详情

javascript跨域

这几天整理了Javascript跨域的东西,终于比较完整了附上CORS代码:1functioncreateCORSRequest(method,url){2varxhr=newXMLHttpRequest();3if("withCredentials"inxhr){4xhr.open(method,url,true);5}elseif(typeofXDomainRequest!="undefine 查看详情

跨域:跨域及解决方法(代码片段)

一、什么是跨域广义的跨域包括:资源跳转:超链接<a>跳转、重定向、表单提交资源嵌入:link、ifram、script、img,以及css样式中的background:url()、@font-face()等外链接脚本请求:js的ajax请求、js或DOM中的跨域操作狭义的跨域:... 查看详情

vue跨域解决方法

针对不在同一服务器,很可能出现跨域问题,解决方法注意:修改了配置文件,需要重启才能生效 查看详情

jsonp跨域ajax跨域get方法

原理: 就是利用<script>标签没有跨域限制的,从而达到与第三方网站通讯的目的。当需要通讯时,本站脚本创建一个<script>标签,src地址指向第三方网站的的一个网址。形如:    <scriptsrc="http://www.abc... 查看详情

ajax跨域json跨域socket跨域和canvas跨域等同源策略限制的解决方法

...三者都同样才属于同域。不符合上述定义的请求,则称为跨域。相信每一个开发者都曾遇到过跨域请求的情况,尽管情况不一样,但问题的本质都能够归为浏览器出于安全考虑下的同源策略的限制。跨域的情形有非常多,最常见... 查看详情

解决跨域的方法

前端解决跨域的方法都是基于<script>标签可以跨域请求平时的ajax请求所经历的过程constxhr=newXMLHttpRequest()xhr.onreadystatechange=function()switch(xhr.readyState)case0://UNSENT(未打开)debuggerbreakcase1://OPENED(未发送)debuggerbreakc 查看详情

http跨域

一、传统ajax跨域访问是一个老问题了,解决方法很多,比较常用的是JSONP方法,JSONP方法是一种非官方方法,而且这种方法只支持GET方式,不如POST方式安全。即使使用jQuery的jsonp方法,type设为POST,也会自动变为GET。官方问题说... 查看详情

jsonp跨域uncaughtsyntaxerror:unexpectedtoken:解决方法

[jQuery]Ajax实现跨域访问JSONAjax跨域访问JSON环境:.net4.0+jQuery+JSON.net因为在跨域实现,所以这里新建网站,这个网站只需要Ashx文件publicvoidProcessRequest(HttpContextcontext){string strJson="[{"id":"100009","name":"mayixue","link":"www 查看详情

跨域和非跨域获取iframe页面高度的方法

跨域方法:第一步,在主页面里插入代码://假设主域名是www.aaa.com 需要插入的跨域域名为www.bbb.com<iframesrc="http://www.bbb.com/index.html"width="100%"height="100%"id="iframepage"name="iframepage"onLoad="iFrameHeight()"frameborde 查看详情

[跨域]跨域解决方法之ngnix反向代理(代码片段)

跨域原理:http://www.cnblogs.com/Alear/p/8758331.html 介绍Ngnix之前,我么先来介绍下代理是什么~  代理相当于中间人,中介的概念  代理分为正向代理和反向代理。(PS:本文介绍的解决跨域方法用的是反向代理)    正向代理... 查看详情