跨域

作者: my木子 | 来源:发表于2021-05-20 09:12 被阅读0次

    跨域

    • 广义跨域 是指一个域下的文档或脚本试图去请求另一个域下的资源
      1. 资源跳转: a 链接、重定向、表单提交
      2. 资源嵌入: linkscriptimgframeDOM 标签,还有样式中 background:url()@font-face()等文件外链
      3. 脚本请求: JS发起的 ajax 请求domJS对象 的跨域操作等
    • 我们通常所说的跨域是 狭义跨域,是由浏览器同源策略限制的一类请求场景

    同源策略

    • 同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSSCSFR 等攻击
    • 同源是指 协议 + 域名 + 端口 三者必须相同
    • 同源策略限制行为,CookieLocalStorageIndexDB 无法读取;DOMJS对象 无法获得;ajax 请求 无法发送

    跨域场景

    • 同一域名,不同文件或路径,允许跨域
      http://www.api.com/a.jshttp://www.api.com/b.jshttp://www.api.com/lab/c.js
    • 同一域名,不同端口,不允许跨域
      http://www.api.com:8000/a.jshttp://www.baidu.com:8080/b.js
    • 同一域名,不同协议,不允许跨域
      http://www.api.com/a.jshttps://www.baidu.com/b.js
    • 域名和域名对应相同ip,不允许跨域
      http://www.api.com/a.jshttp://192.168.4.12/b.js
    • 主域相同,子域不同,不允许跨域
      http://www.api.com/a.jshttp://x.api.com/b.jshttp://api.com/c.js
    • 不同域名,不允许跨域
      http://www.api1.com/a.jshttp://www.api2.com/b.js

    跨域解决方案

    • 通过 jsonp 跨域,但只能只能实现 get 一种请求
    // 原生实现
        var script = document.createElement('script');
        script.type = 'text/javascript';
    
        // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
        script.src = 'http://www.api.com:8080/list?type=1&callback=handleCallback';
        document.head.appendChild(script);
    
        // 回调执行函数
        function handleCallback(res) {
            alert(JSON.stringify(res));
        }
    
    // jquery
      $.ajax({
        url: 'http://www.api.com:8080/list',
        type: 'get',
        dataType: 'jsonp',  // 请求方式为jsonp
        jsonpCallback: "handleCallback",    // 自定义回调函数名
        data: {}
    });
    
    // vue.js
    this.$http.jsonp('http://www.api.com:8080/list', {
        params: {},
        jsonp: 'handleCallback'
    }).then((res) => {
        console.log(res); 
    })
    
    • Vue proxy 代理(nodejs 中间件代理跨域)
    /// webpack.config.js
    module.exports = {
        entry: {},
        module: {},
        ...
        devServer: {
            historyApiFallback: true,
            proxy: [{
                context: '/list',
                target: 'http://www.api2.com:8080',  // 代理跨域目标接口
                changeOrigin: true,
                secure: false,  // 当代理某些https服务报错时用
                cookieDomainRewrite: 'www.api1.com'  // 可以为false,表示不修改
            }],
            noInfo: true
        }
    }
    
    • 跨域资源共享(CORS)
      普通跨域请求,只服务端设置 Access-Control-Allow-Origin 即可,前端无须设置,若要带 cookie 请求,前后端都需要设置
      由于同源策略的限制,所读取的 cookie 为跨域请求接口所在域的 cookie,而非当前页。如果想实现当前页cookie的写入,可通过 NodeJs中间件代理cookieDomainRewrite 参数的设置
    // 原生 ajax
    xhr.withCredentials = true;
    // IE8/9需用window.XDomainRequest兼容
    
    // jQuery ajax
    $.ajax({
        ...
       xhrFields: {
           withCredentials: true    // 前端设置是否带cookie
       },
       crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
        ...
    });
    
    // Vue axios
    axios.defaults.withCredentials = true
    
    // Vue vue-resource
    Vue.http.options.credentials = true
    
    • document.domain + iframe跨域
    • location.hash + iframe
    • window.name + iframe跨域
    • postMessage跨域
    • nginx代理跨域
    • WebSocket协议跨域

    相关文章

      网友评论

          本文标题:跨域

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