跨域 订阅
《跨域》是漠粟写的网络小说连载于红袖添香网。 展开全文
《跨域》是漠粟写的网络小说连载于红袖添香网。
信息
作    者
漠粟
小说进度
连载
中文名
跨域
连载网站
红袖添香网
跨域小说类型
推理悬疑
收起全文
精华内容
参与话题
问答
  • 什么是跨域跨域解决方法

    万次阅读 多人点赞 2018-12-14 19:22:02
    一、为什么会出现跨域问题 出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建...

    一、为什么会出现跨域问题

    出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

    二、什么是跨域

    当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

    当前页面url 被请求页面url 是否跨域 原因
    http://www.test.com/ http://www.test.com/index.html 同源(协议、域名、端口号相同)
    http://www.test.com/ https://www.test.com/index.html 跨域 协议不同(http/https)
    http://www.test.com/ http://www.baidu.com/ 跨域 主域名不同(test/baidu)
    http://www.test.com/ http://blog.test.com/ 跨域 子域名不同(www/blog)
    http://www.test.com:8080/ http://www.test.com:7001/ 跨域 端口号不同(8080/7001)

    三、非同源限制

    【1】无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

    【2】无法接触非同源网页的 DOM

    【3】无法向非同源地址发送 AJAX 请求

    四、跨域解决方法

    【1】设置document.domain解决无法读取非同源网页的 Cookie问题

    因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)

    // 两个页面都设置
    document.domain = 'test.com';

    【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】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); 
    })

    【4】CORS

    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

    【服务端设置】

    服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。

    ① Java后台

    /*
     * 导入包:import javax.servlet.http.HttpServletResponse;
     * 接口参数中定义:HttpServletResponse response
     */
    
    // 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
    response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 
    
    // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
    response.setHeader("Access-Control-Allow-Credentials", "true"); 
    
    // 提示OPTIONS预检时,后端需要设置的两个常用自定义头
    response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

    ② Nodejs后台

    var http = require('http');
    var server = http.createServer();
    var qs = require('querystring');
    
    server.on('request', function(req, res) {
        var postData = '';
    
        // 数据块接收中
        req.addListener('data', function(chunk) {
            postData += chunk;
        });
    
        // 数据接收完毕
        req.addListener('end', function() {
            postData = qs.parse(postData);
    
            // 跨域后台设置
            res.writeHead(200, {
                'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
                'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议+域名+端口)
                /* 
                 * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),
                 * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问
                 */
                'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'  // HttpOnly的作用是让js无法读取cookie
            });
    
            res.write(JSON.stringify(postData));
            res.end();
        });
    });
    
    server.listen('8080');
    console.log('Server is running at port 8080...');

    ③ PHP后台

    <?php
     header("Access-Control-Allow-Origin:*");
    

    ④ Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下内容即可

    Header set Access-Control-Allow-Origin *

    文章每周持续更新,可以微信搜索「 前端大集锦 」第一时间阅读,回复【视频】【书籍】领取200G视频资料和30本PDF书籍资料

    展开全文
  • 跨域

    千次阅读 2019-01-05 10:54:40
    什么是跨域跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。 广义的跨域: 1.) 资源跳转: A链接、重定向、表单提交 2.) 资源嵌入: &lt;link&gt;、&lt;script&...

    什么是跨域?

    跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。

    广义的跨域:

    1.) 资源跳转: A链接、重定向、表单提交
    2.) 资源嵌入: <link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链
    3.) 脚本请求: js发起的ajax请求、dom和js对象的跨域操作等

    其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。

    什么是同源策略?
    同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

    同源策略限制以下几种行为:

    1.) Cookie、LocalStorage 和 IndexDB 无法读取
    2.) DOM 和 Js对象无法获得
    3.) AJAX 请求不能发送

    常见跨域场景

    URL                                      说明                    是否允许通信
    http://www.domain.com/a.js
    http://www.domain.com/b.js         同一域名,不同文件或路径           允许
    http://www.domain.com/lab/c.js
    
    http://www.domain.com:8000/a.js
    http://www.domain.com/b.js         同一域名,不同端口                不允许
     
    http://www.domain.com/a.js
    https://www.domain.com/b.js        同一域名,不同协议                不允许
     
    http://www.domain.com/a.js
    http://192.168.4.12/b.js           域名和域名对应相同ip              不允许
     
    http://www.domain.com/a.js
    http://x.domain.com/b.js           主域相同,子域不同                不允许
    http://domain.com/c.js
     
    http://www.domain1.com/a.js
    http://www.domain2.com/b.js        不同域名                         不允许

    跨域解决方案

    1、 通过jsonp跨域
    2、 document.domain + iframe跨域
    3、 location.hash + iframe
    4、 window.name + iframe跨域
    5、 postMessage跨域
    6、 跨域资源共享(CORS)
    7、 nginx代理跨域
    8、 nodejs中间件代理跨域
    9、 WebSocket协议跨域

    一、 通过jsonp跨域

    通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。

    1.)原生实现:

     <script>
        var script = document.createElement('script');
        script.type = 'text/javascript';
    
        // 传参并指定回调执行函数为onBack
        script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
        document.head.appendChild(script);
    
        // 回调执行函数
        function onBack(res) {
            alert(JSON.stringify(res));
        }
     </script>

    服务端返回如下(返回时即执行全局函数):

    onBack({"status": true, "user": "admin"})

    2.)jquery ajax:

    $.ajax({
        url: 'http://www.domain2.com:8080/login',
        type: 'get',
        dataType: 'jsonp',  // 请求方式为jsonp
        jsonpCallback: "onBack",    // 自定义回调函数名
        data: {}
    });

    3.)vue.js:

    this.$http.jsonp('http://www.domain2.com:8080/login', {
        params: {},
        jsonp: 'onBack'
    }).then((res) => {
        console.log(res); 
    })

    后端node.js代码示例:

    var querystring = require('querystring');
    var http = require('http');
    var server = http.createServer();
    
    server.on('request', function(req, res) {
        var params = qs.parse(req.url.split('?')[1]);
        var fn = params.callback;
    
        // jsonp返回设置
        res.writeHead(200, { 'Content-Type': 'text/javascript' });
        res.write(fn + '(' + JSON.stringify(params) + ')');
    
        res.end();
    });
    
    server.listen('8080');
    console.log('Server is running at port 8080...');

    jsonp缺点:只能实现get一种请求。

    二、 document.domain + iframe跨域

    此方案仅限主域相同,子域不同的跨域应用场景。

    实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

    1.)父窗口:(http://www.domain.com/a.html)

    <iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
    <script>
        document.domain = 'domain.com';
        var user = 'admin';
    </script>

    2.)子窗口:(http://child.domain.com/b.html)

    <script>
        document.domain = 'domain.com';
        // 获取父窗口中变量
        alert('get js data from parent ---> ' + window.parent.user);
    </script>

    三、 location.hash + iframe跨域

    实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

    具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。

    1.)a.html:(http://www.domain1.com/a.html)

    <iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
    <script>
        var iframe = document.getElementById('iframe');
    
        // 向b.html传hash值
        setTimeout(function() {
            iframe.src = iframe.src + '#user=admin';
        }, 1000);
        
        // 开放给同域c.html的回调方法
        function onCallback(res) {
            alert('data from c.html ---> ' + res);
        }
    </script>

    2.)b.html:(http://www.domain2.com/b.html)

    <iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe>
    <script>
        var iframe = document.getElementById('iframe');
    
        // 监听a.html传来的hash值,再传给c.html
        window.onhashchange = function () {
            iframe.src = iframe.src + location.hash;
        };
    </script>

    3.)c.html:(http://www.domain1.com/c.html)

    <script>
        // 监听b.html传来的hash值
        window.onhashchange = function () {
            // 再通过操作同域a.html的js回调,将结果传回
            window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));
        };
    </script>

    四、 window.name + iframe跨域

    window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

    1.)a.html:(http://www.domain1.com/a.html)

    var proxy = function(url, callback) {
        var state = 0;
        var iframe = document.createElement('iframe');
    
        // 加载跨域页面
        iframe.src = url;
    
        // onload事件会触发2次,第1次加载跨域页,并留存数据于window.name
        iframe.onload = function() {
            if (state === 1) {
                // 第2次onload(同域proxy页)成功后,读取同域window.name中数据
                callback(iframe.contentWindow.name);
                destoryFrame();
    
            } else if (state === 0) {
                // 第1次onload(跨域页)成功后,切换到同域代理页面
                iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
                state = 1;
            }
        };
    
        document.body.appendChild(iframe);
    
        // 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)
        function destoryFrame() {
            iframe.contentWindow.document.write('');
            iframe.contentWindow.close();
            document.body.removeChild(iframe);
        }
    };
    
    // 请求跨域b页面数据
    proxy('http://www.domain2.com/b.html', function(data){
        alert(data);
    });

    2.)proxy.html:(http://www.domain1.com/proxy....
    中间代理页,与a.html同域,内容为空即可。

    3.)b.html:(http://www.domain2.com/b.html)

    <script>
        window.name = 'This is domain2 data!';
    </script>

    总结:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

    五、 postMessage跨域

    postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
    a.) 页面和其打开的新窗口的数据传递
    b.) 多窗口之间消息传递
    c.) 页面与嵌套的iframe消息传递
    d.) 上面三个场景的跨域数据传递

    用法:postMessage(data,origin)方法接受两个参数
    data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
    origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

    1.)a.html:(http://www.domain1.com/a.html)

    <iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
    <script>       
        var iframe = document.getElementById('iframe');
        iframe.onload = function() {
            var data = {
                name: 'aym'
            };
            // 向domain2传送跨域数据
            iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
        };
    
        // 接受domain2返回数据
        window.addEventListener('message', function(e) {
            alert('data from domain2 ---> ' + e.data);
        }, false);
    </script>

    2.)b.html:(http://www.domain2.com/b.html)

    <script>
        // 接收domain1的数据
        window.addEventListener('message', function(e) {
            alert('data from domain1 ---> ' + e.data);
    
            var data = JSON.parse(e.data);
            if (data) {
                data.number = 16;
    
                // 处理后再发回domain1
                window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
            }
        }, false);
    </script>

    六、 跨域资源共享(CORS)

    普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。

    需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。如果想实现当前页cookie的写入,可参考下文:七、nginx反向代理中设置proxy_cookie_domain 和 八、NodeJs中间件代理中cookieDomainRewrite参数的设置。

    目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。

    1、 前端设置:

    1.)原生ajax

    // 前端设置是否带cookie
    xhr.withCredentials = true;

    示例代码:

    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);
        }
    };

    2.)jQuery ajax

    $.ajax({
        ...
       xhrFields: {
           withCredentials: true    // 前端设置是否带cookie
       },
       crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
        ...
    });

    3.)vue框架

    a.) axios设置:

    axios.defaults.withCredentials = true

    b.) vue-resource设置:

    Vue.http.options.credentials = true

    2、 服务端设置:

    若后端设置成功,前端浏览器控制台则不会出现跨域报错信息,反之,说明没设成功。

    1.)Java后台:

    /*
     * 导入包:import javax.servlet.http.HttpServletResponse;
     * 接口参数中定义:HttpServletResponse response
     */
    
    // 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
    response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 
    
    // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
    response.setHeader("Access-Control-Allow-Credentials", "true"); 
    
    // 提示OPTIONS预检时,后端需要设置的两个常用自定义头
    response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

    2.)Nodejs后台示例:

    var http = require('http');
    var server = http.createServer();
    var qs = require('querystring');
    
    server.on('request', function(req, res) {
        var postData = '';
    
        // 数据块接收中
        req.addListener('data', function(chunk) {
            postData += chunk;
        });
    
        // 数据接收完毕
        req.addListener('end', function() {
            postData = qs.parse(postData);
    
            // 跨域后台设置
            res.writeHead(200, {
                'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
                'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议+域名+端口)
                /* 
                 * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),
                 * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问
                 */
                'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'  // HttpOnly的作用是让js无法读取cookie
            });
    
            res.write(JSON.stringify(postData));
            res.end();
        });
    });
    
    server.listen('8080');
    console.log('Server is running at port 8080...');

    七、 nginx代理跨域

    1、 nginx配置解决iconfont跨域

    浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。

    location / {
      add_header Access-Control-Allow-Origin *;
    }

    2、 nginx反向代理接口跨域

    跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。

    实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

    nginx具体配置:

    #proxy服务器
    server {
        listen       81;
        server_name  www.domain1.com;
    
        location / {
            proxy_pass   http://www.domain2.com:8080;  #反向代理
            proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
            index  index.html index.htm;
    
            # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
            add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
            add_header Access-Control-Allow-Credentials true;
        }
    }

    1.) 前端代码示例:

    var xhr = new XMLHttpRequest();
    
    // 前端开关:浏览器是否读写cookie
    xhr.withCredentials = true;
    
    // 访问nginx中的代理服务器
    xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
    xhr.send();

    2.) Nodejs后台示例:

    var http = require('http');
    var server = http.createServer();
    var qs = require('querystring');
    
    server.on('request', function(req, res) {
        var params = qs.parse(req.url.substring(2));
    
        // 向前台写cookie
        res.writeHead(200, {
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本无法读取
        });
    
        res.write(JSON.stringify(params));
        res.end();
    });
    
    server.listen('8080');
    console.log('Server is running at port 8080...');

    八、 Nodejs中间件代理跨域

    node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。

    1、 非vue框架的跨域(2次跨域)

    利用node + express + http-proxy-middleware搭建一个proxy服务器。

    1.)前端代码示例:

    var xhr = new XMLHttpRequest();
    
    // 前端开关:浏览器是否读写cookie
    xhr.withCredentials = true;
    
    // 访问http-proxy-middleware代理服务器
    xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
    xhr.send();

    2.)中间件服务器:

    var express = require('express');
    var proxy = require('http-proxy-middleware');
    var app = express();
    
    app.use('/', proxy({
        // 代理跨域目标接口
        target: 'http://www.domain2.com:8080',
        changeOrigin: true,
    
        // 修改响应头信息,实现跨域并允许带cookie
        onProxyRes: function(proxyRes, req, res) {
            res.header('Access-Control-Allow-Origin', 'http://www.domain1.com');
            res.header('Access-Control-Allow-Credentials', 'true');
        },
    
        // 修改响应信息中的cookie域名
        cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
    }));
    
    app.listen(3000);
    console.log('Proxy server is listen at port 3000...');

    3.)Nodejs后台同(六:nginx)

    2、 vue框架的跨域(1次跨域)

    利用node + webpack + webpack-dev-server代理接口跨域。在开发环境下,由于vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以页面与代理接口之间不再跨域,无须设置headers跨域信息了。

    webpack.config.js部分配置:

    module.exports = {
        entry: {},
        module: {},
        ...
        devServer: {
            historyApiFallback: true,
            proxy: [{
                context: '/login',
                target: 'http://www.domain2.com:8080',  // 代理跨域目标接口
                changeOrigin: true,
                secure: false,  // 当代理某些https服务报错时用
                cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
            }],
            noInfo: true
        }
    }

    九、 WebSocket协议跨域

    WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
    原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

    1.)前端代码:

    <div>user input:<input type="text"></div>
    <script src="./socket.io.js"></script>
    <script>
    var socket = io('http://www.domain2.com:8080');
    
    // 连接成功处理
    socket.on('connect', function() {
        // 监听服务端消息
        socket.on('message', function(msg) {
            console.log('data from server: ---> ' + msg); 
        });
    
        // 监听服务端关闭
        socket.on('disconnect', function() { 
            console.log('Server socket has closed.'); 
        });
    });
    
    document.getElementsByTagName('input')[0].onblur = function() {
        socket.send(this.value);
    };
    </script>

    2.)Nodejs socket后台:

    var http = require('http');
    var socket = require('socket.io');
    
    // 启http服务
    var server = http.createServer(function(req, res) {
        res.writeHead(200, {
            'Content-type': 'text/html'
        });
        res.end();
    });
    
    server.listen('8080');
    console.log('Server is running at port 8080...');
    
    // 监听socket连接
    socket.listen(server).on('connection', function(client) {
        // 接收信息
        client.on('message', function(msg) {
            client.send('hello:' + msg);
            console.log('data from client: ---> ' + msg);
        });
    
        // 断开处理
        client.on('disconnect', function() {
            console.log('Client socket has closed.'); 
        });
    });
    展开全文
  • vue中axios跨域请求

    千次阅读 2019-06-22 13:22:31
    vue中axios跨域请求 1.axios 是 第三方库 使用方法: 使用 npm: $ npm install axios 使用 bower: $ bower install axios 使用 cdn: <script src="https://unpkg.com/axios/dist/axios.min.js"></...

    vue中axios跨域请求

    1.axios 是 第三方库
    使用方法:

    • 使用 npm:
        $ npm install axios
    
    • 使用 bower:
    $ bower install axios
    
    • 使用 cdn:
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    

    axios get 请求示例

    HTML代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
        <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <button @click="getData">get-mock-data</button>
            <button @click="get_api_data"> get-api-data </button>
        </div>
        
    </body>
    </html>
    

    js代码

    <script>
              console.log( axios )
            // 当我们引入axios cdn后会全局暴露出一个axios对象
            new Vue ({
                el:"#app",
                methods:{
                    
                      getData(){
                        // var p = axios({
                        //     url:'./data/name.json'
                        // });
                        // console.log(p);//axios是一个promise对象
    
                        axios({
                            url:"./data/name.json",
                            method:'get',//method默认是get请求
                        }).then(function(res){
                            console.log(res)
                            // axios会对我们请求来的结果进行再一次的封装( 让安全性提高 )
                        }).catch(err=>{
                            console.log(err)
                        })
    
                    },
    

    请求结果 : axios会对我们请求来的结果进行再一次的封装( 让安全性提高 )
    在这里插入图片描述

     //get在线跨域请求
                   get_api_data(){
                      axios({
                          url:'https://请求地址',//在线跨域请求
                          method:"GET",//默认是get请求
                          headers:{//设置请求头
                              'X-Client-Info':' {"a":"3000","ch":"1002","v":"5.0.4","e":"15611234619393093477584"}',
                              'X-Host': 'mall.film-ticket.film.list',
                          },
                          params:{//?search后面的值写在params中
                              cityId: 330100,
                              pageNum: 1,
                              pageSize: 10,
                              type: 1,
                              k: 3969168,
                          }
                      }).then(function(val){
                          console.log(val) // axios会对我们请求来的结果进行再一次的封装( 让安全性提高 )
                      }).catch(function(err){
                          console.log(err)
                      })
                  },
              }
          })
      </script>
    

    get跨域请求中params:中的值对应hearders中Query String Parameters
    在这里插入图片描述
    在这里插入图片描述
    get方法总结:

    A: 无参数
            axios.get(url).then(res=>console.log(res).catch(error=>conosle.log(error))
     B: 有参数
            axios({
                url: 'http://xxx',
                method: 'get' //默认就是get,这个可以省略,
                params: {
                    key: value
                }
            })
    

    axios post 请求示例

    html代码
     <button  @click="postData"> post-data </button>
     
     js代码
           postData(){
                        let params = new URLSearchParams()//得到params对象,用来接收请求参数
                        // params.append( key, value )  key是参数名,value是参数值
                        //传递参数值
                         params.append( 'a', 2 )
                         params.append( 'b', 2 )
    
                        axios({
                            url:'http//localhost/php',
                            method:'post',
                            headers:{//请求头设置为表单提交的请求头
                                'Content-Type':"application/x-www-form-urlencoded"
                            },
                            data:params,
                        }).then( function (val) {
                            console.log(res)
                        }).catch( function (error) { 
                            console.log(error)
                        })
                    }
                }
                官方文档中axios post请求案例有点问题,请求会出现跨域问题;
    			以上示例为解决官方文档存在问题的写法;
    

    post方法总结

    //对于post请求可以统一设置一个请求头,后面所有post请求就可以不用单独设置请求头了
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    
     // 具体语法
     let params = new URLSearchParams()//得到params对象,用来接收请求参数
    
    // params.append(key,value) //请求参数写成键值对key就是参数名,value就是参数值
    
    params.append('a',1)
    params.append('b',2)
    
    axios({
        url: 'http://localhost/post.php',
        method: 'post',
        data: params,//将请求参数写入data;
          headers: {  //单个请求设置请求头
           'Content-Type': "application/x-www-form-urlencoded"
        }
    })
    .then(res => {
        console.log( res )
    })
    .catch( error => {
        if( error ){
        throw error
    }
    })
    
    展开全文
  • 跨域问题解决方案:CORS Access to XMLHttpRequest at '*' from origin '*' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-...

    跨域问题解决方案:CORS

    Access to XMLHttpRequest at '*' from origin '*' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    从源'本地路径'访问 '目标路径(请求链接)'文本传输请求已被CORS策略阻塞:对预置请求的响应未通过访问控制检查:请求的资源上不存在'Access- control - allow - origin '报头。

    错误原因:

    本地路径和目标路径不是同一个域名下引起的跨域问题,并且,就算两个域名是同一个一级域名不同二级域名的时候,例如 a.baidu.com  和 b.baidu.com 是属于不同域的,也是会出现这个问题

    介绍

    出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。

    注:这段描述不准确,并不一定是浏览器限制了发起跨站请求,也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。

    CORS(跨源资源共享)是一个系统,由传输HTTP标头组成,用于确定浏览器是否阻止前端JavaScript代码访问跨源请求的响应

    同源安全政策禁止以资源跨域访问。但CORS使Web服务器能够表示他们希望选择允许跨资源访问其资源。

    跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器  让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求

    如,站点 http://domain-a.com 的某 HTML 页面通过 <img> 的 src 请求 http://domain-b.com/image.jpg。网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源。

    跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。

     

    解决方案:

    1、如果跨域请求发生在相同一级域名不同二级域名之间

    例如:a.baidu.com  和 b.baidu.com

    跨域直接在邀请求的接口页面中强制设置域为一级域     document.domain = "baidu.com";

    2、设置接口允许ajax跨域访问

    在服务器aspx页面头文件里加:

    <meta http-equiv="Access-Control-Allow-Origin" content="*" />

    在web.config文件中的 system.webServer 节点下 增加如下配置

    <system.webServer>  
        <httpProtocol> 
            <customHeaders> 
                <add name="Access-Control-Allow-Methods" value="OPTIONS,POST,GET"/> 
                <add name="Access-Control-Allow-Headers" value="x-requested-with"/> 
                <add name="Access-Control-Allow-Origin" value="*" /> 
            </customHeaders> 
        </httpProtocol> 
    </system.webServer>
    

    网上说的解决方案都是Internet Explorer 8 、9使用 XDomainRequest 对象实现CORS。是不是有这么复杂?于是博主各种百度寻找解决方案。最后发现在调用处指定 jQuery.support.cors = true; 这一句就能解决IE8、9的问题了

    这句话的意思就是指定浏览器支持跨域。IE9以上版本的浏览器、谷歌、火狐等都默认支持跨域,而IE8、9却默认不支持跨域,需要我们指定一下。

    //例如
    jQuery.support.cors = true;
    var ApiUrl = "http://b.baidu.com";
    $(function () {
        $.ajax({
            type: "get",
            url: ApiUrl + "api/Charging/GetAllChargingData",
            data: {},
            success: function (data, status) {
                if (status == "success") {
                    alert("ok");
                }
            },
            error: function (e) {
                alert("error");
            },
            complete: function () {
    
            }
        });
    });

    注:我这里设置的*是任意的请求都可以访问,如果需要限制替换成自己的访问地址就可以了。

    参考资料:

     HTTP访问控制(CORS)   https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

    CORS(跨源资源共享)      https://developer.mozilla.org/en-US/docs/Glossary/CORS

     

     

    你有困难我帮忙,我住隔壁我姓王。----------------- 你隔壁的老王宣。

    展开全文
  • 跨域问题(CORS / Access-Control-Allow-Origin)

    万次阅读 多人点赞 2018-11-24 23:11:50
    1、前言 最近在项目中,调用Eureka REST接口时,出现了CORS跨越问题(Cross-origin resource sharing),在此与大家进行分享,避免多走些弯路。 项目前端(http://localhost:9000)通过Ajax方式调用Eureka REST ...
  • 解决ajax跨域问题【5种解决方案】

    万次阅读 多人点赞 2018-09-02 21:31:33
    什么是跨域问题? 跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是...
  • Vue之Axios跨域问题解决方案

    万次阅读 多人点赞 2019-02-19 14:32:31
    背景:因为axios中只能使用get和post方法来进行请求数据,没有提供jsonp等方法进行跨域访问数据 axios中文网址:https://www.kancloud.cn/yunye/axios/234845 // axios 中的GET请求 axios.get('/user', { ...
  • 解决跨域问题的8种方案(最新最全)

    万次阅读 多人点赞 2019-02-18 17:47:01
    转自 PheonixHkbxoic 的《前端解决跨域问题的8种方案(最新最全)》 原址:https://www.cnblogs.com/PheonixHkbxoic/p/5760838.html 1.同源策略如下: URL 说明 是否允许通信 http://www.a.com/a.js ...
  • 什么是跨域?如何解决跨域问题?

    万次阅读 多人点赞 2017-07-31 20:29:48
    什么是跨域? 浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域 域名: 主域名不同 http://www.baidu.com/index.html –&amp;gt;http://www.sina.com/test.js 子域名...
  • 八种方式实现跨域请求

    万次阅读 多人点赞 2017-06-11 22:52:54
    前端开发中我们经常会遇到跨域请求的情况,处理跨域请求方式很多,特整理如下: 浏览器的同源策略​ 提到跨域不能不先说一下”同源策略”。 ​ 何为同源?只有当协议、端口、和域名都相同的页面,则两个页面具有...
  • SpringBoot解决CORS跨域(@CrossOrigin)

    万次阅读 多人点赞 2018-07-21 10:59:20
    一、关于跨域介绍 在前后分离的架构下,跨域问题难免会遇见比如,站点 http://domain-a.com 的某 HTML 页面通过 的 src 请求 http://domain-b.com/image.jpg。网络上的许多页面都会加载来自不同域的CSS样式表,图像...
  • Axiso解决跨域访问

    万次阅读 多人点赞 2018-05-31 13:10:43
    这里以访问豆瓣Top250为例,直接访问如下: this.$axios.get(&amp;amp;amp;amp;amp;quot;http://api.douban.com/v2/movie/top250&amp;amp;amp;amp;amp;quot;) .then(res=&amp;amp;...{
  • jsonp跨域原理解析

    万次阅读 多人点赞 2018-09-01 19:25:07
    由于浏览器同源策略的限制,非同源下的请求,都会产生跨域问题,jsonp即是为了解决这个问题出现的一种简便解决方案。 同源策略即:同一协议,同一域名,同一端口号。当其中一个不满足时,我们的请求即会发生跨域...
  • 前端解决跨域问题

    万次阅读 多人点赞 2019-05-12 15:48:54
    首先要了解浏览器跨域的问题源自哪里 浏览器跨域问题是源于浏览器的同源策略,,协议,域名,端口,三者有其中一个不一致就属于跨域。 URL网址的组成: http://www.baidu.com:80/index.html?username=xxx&...
  • 什么是跨域?怎么解决跨域问题?

    万次阅读 多人点赞 2016-06-15 17:32:16
    什么是跨域跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。 所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子: ...
  • ## 问题:开发环境下 跨域访问正式环境服务器API失败 . **额外描述:根据一些博客,已经做了跨域访问的作业。目前部分API访问成功,例如:获取图形验证码。但是登入验证访问API失败。** . **访问API...
  • 解决iframe跨域问题

    千次阅读 2019-05-15 14:32:50
    目录场景解决跨域一:使用代理页面(来自 [伯纳乌的追风少年](https://www.jianshu.com/p/9d90d3333215))解决2:使用postmessage 场景 在开发中,发现部分页面内容在不同项目中重复率极高,像导航栏这种,不同项目都...
  • 后端跨域

    千次阅读 2020-11-25 21:06:33
    DRF跨域后端解决之django-cors-headers 在使用django-rest-framework开发项目的时候我们总是避免不了跨域的问题,因为现在大多数的项目都是前后端分离,前后端项目部署在不同的web服务器上,因为我们是后端程序员,...
  • 如何实现跨域

    万次阅读 2019-07-02 11:00:36
    如何实现跨域跨域:当浏览器执行脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域。 这里的同源指访问的协议、域名、端口都相同。 同源策略是由 Netscape 提出的著名安全策略,是浏览器最...
  • 常见跨域

    千次阅读 2020-09-05 20:12:05
    常见跨域 HTML页面中一些允许指定路径的元素具有跨域特性: <link> 元素 <script> 元素 <img> 元素 <ifrane> 元素 <script src="https://cdn.bootcss.com/iquery/3.3.1/jquery.is">&...
  • # 问题:video.js播放m3u8视频无法跨域访问 今天使用video.js播放m3u8视频时遇到了跨域的问题 我的请求路径是www.xuecheng.com/video.html ![图片说明]...
  • ##我接受文件的后台都做了跨域的处理,目前是上传请求能到后台且文件存储成功,但是editorMD 还是判断为跨域, 出现错误 image-dialog.js:171 Uncaught DOMException: Blocked a frame with origin ...
  • 最近连续两个朋友问我跨域相关问题,我猜想可能不少朋友也遇到类似问题,我打算写个博客聊一下我实际使用的配置, 先说明一下,我并不太了解这配置,没精力去了解太多,但我觉得其中有一些关键的小注意点,可能有些...
  • Springboot处理CORS跨域请求的三种方法

    万次阅读 多人点赞 2020-06-08 11:23:52
    Springboot跨域问题,是当前主流web开发人员都绕不开的难题。但我们首先要明确以下几点 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境 跨域请求能发出去,服务端能收到请求并正常返回...
  • 处理图片跨域问题

    千次阅读 2020-04-16 14:33:43
    <meta name="referrer" content="no-referrer"/>
  • 跨域跨域访问

    万次阅读 2018-05-18 15:49:54
    什么是跨域 跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域 为什么...
  • 我目前的问题 就是跨域问题 查了老半天 我同一个服务器上 有解析四五个域名 我要从wwww.zuiwuliao.cn域名跟cdn.2177.cn域名 拿一张图片在用canvas绘图 问题来了 我还没有请求 就先报跨域错 执行后不生成 我实在不...
  • 九、Spring Boot 优雅的实现CORS跨域

    万次阅读 多人点赞 2019-12-04 09:56:40
    一般的情况下,都是前后端分离的,我这个架手架的初衷也是前后端进行分离,所以这里就涉及到一个很严重的问题啦,当协议,端口,IP三者有其一不同就会产生跨域,所以需要做跨域支持。 测试跨域的文件 在这...

空空如也

1 2 3 4 5 ... 20
收藏数 73,657
精华内容 29,462
关键字:

跨域