跨域详解

作者: 你这个锤子 | 来源:发表于2023-11-16 16:08 被阅读0次

    定义:协议/主机/端口号,这三个条件其中一个不一样,就属于跨域;

    image.png

    跨域其实是遵循浏览器的一个同源策略,浏览器为了安全考虑,阻止恶意的攻击,减少可能被攻击的媒介。不遵循同源规则的,不允许访问。

    解决跨域:

    1,JSONP
    JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
    核心思想:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

    原生实现
    <script src="http://test.com/data.php?callback=dosomething"></script>
    // 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
     
    // 处理服务器返回回调函数的数据
    <script type="text/javascript">
        function dosomething(res){
            // 处理获得的数据
            console.log(res.data)
        }
    </script>
    
    
    jQuery ajax:
    $.ajax({
        url: 'http://www.test.com:8080/login',
        type: 'get',
        dataType: 'jsonp',  // 请求方式为jsonp
        jsonpCallback: "handleCallback",    // 自定义回调函数名
        data: {}
    });
    
    vue.js
    this.$http.jsonp('http://www.domain2.com:8080/login', {
        params: {},
        jsonp: 'handleCallback'
    }).then((res) => {
        console.log(res); 
    })
    
    

    2,跨文档通信 API:window.postMessage()
    调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)
    它可用于解决以下方面的问题:

    • 页面和其打开的新窗口的数据传递
    • 多窗口之间消息传递
    • 页面与嵌套的iframe消息传递
    • 上面三个场景的跨域数据传递
    // 父窗口打开一个子窗口
    var openWindow = window.open('http://test2.com', 'title');
    // 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
    openWindow.postMessage('Nice to meet you!', 'http://test2.com');
    

    调用message事件,监听对方发送的消息

    // 监听 message 消息
    window.addEventListener('message', function (e) {
      console.log(e.source); // e.source 发送消息的窗口
      console.log(e.origin); // e.origin 消息发向的网址
      console.log(e.data);   // e.data   发送的消息
    },false);
    

    3,CORS
    跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
    1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
    2、带cookie跨域请求:前后端都需要进行设置
    【前端设置】根据xhr.withCredentials字段判断是否带有cookie

    原生ajax
    var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
    // 前端设置是否带cookie
    xhr.withCredentials = true;
    xhr.open('post', 'http://www.domain2.com:8080/login', true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send('user=admin');
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            alert(xhr.responseText);
        }
    };
    
    jQuery ajax 
    $.ajax({
       url: 'http://www.test.com:8080/login',
       type: 'get',
       data: {},
       xhrFields: {
           withCredentials: true    // 前端设置是否带cookie
       },
       crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
    });
    
    vue-resource
    Vue.http.options.credentials = true
    
    axios
    axios.defaults.withCredentials = true
    

    4,本地代理
    在webpack.config.js中利用 WebpackDevServer 配置本地代理,详情配置查看devServer
    vue项目中也有类似的 vue.config.js 文件用来配置本地代理。
    5,websocket
    Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket 和 HTTP 都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 服务器与 客户端都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
    6,Nginx反向代理
    Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。
    使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。

    参考文章

    相关文章

      网友评论

        本文标题:跨域详解

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