精华内容
下载资源
问答
  • 主要介绍了前端常见跨域解决方案的相关内容,包括对跨域的解释,常见跨域场景以及跨域解决方案,内容丰富,需要的朋友可以参考下。
  • 分享转载:前端常见跨域解决方案 1、 通过jsonp跨域 2、 document.domain + iframe跨域 3、 location.hash + iframe 4、 window.name + iframe跨域 5、 postMessage跨域 6、 跨域资源共享(CORS) 7、 nginx...
  • NULL 博文链接:https://sun123start.iteye.com/blog/2150778
  • 前后端分离H5 跨域解决方案 提供多种解决方法 详情请下载文件 自己看 100%可以解决你的问题
  • 跨域解决的两种方法

    2018-05-24 20:06:46
    跨域:个人简单的理解就是,你本地localhost:8080访问另一个地址192.168.0.1,会出现跨域,原因是跨域要实现同源策略,即:HTTP//IP:port要一样,HTTP和HTTPS会出现跨域,还有就是orgin请求来源是否允许
  • Nodejs Express Ajax跨域请求实例代码,Nodejs Express Ajax跨域请求实例代码
  • 解决ie8、9Ajax跨域问题(前端):jsp引入此js,Jquery Ajax正常写
  • arcgis js跨域解决策略

    2018-08-12 13:35:00
    能够完美解决arcgis js跨域解决问题,该文档详细说明了.NET或者java环境下跨域解决
  • 正常使用AJAX会需要正常考虑跨域问题,所以伟大的程序员们又折腾出了一系列跨域问题的解决方案,如JSONP、flash、ifame、xhr2等等。本文给大家介绍JS跨域解决方案之使用CORS实现跨域,感兴趣的朋友参考下吧
  • 在浏览器查看一个pdf文件时常常不知道怎么显示,这个资源可以很好的帮到你,而且还附有跨域解决办法。
  • 主要介绍了vue-cli3 中跨域解决方案,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
  • 什么是跨域?跨域解决方法

    万次阅读 多人点赞 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 *

    【5】webpack本地代理

     å¾ç

    在webpack.config.js中利用 WebpackDevServer 配置本地代理,详情配置查看devServer

    如下简单配置案例,这样 `http://localhost:8080/api/getUser.php` 的请求就是后端的接口 `http://192.168.25.20:8088/getUser.php`

        devServer: {
            port: 8080,
            proxy: {
                "/api": {
                  target: "http://192.168.25.20:8088" // 后端接口
                }
            }
        }

    【6】websocket

    Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket 和 HTTP 都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 服务器与 客户端都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

    【7】Nginx反向代理

    Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。

    使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。

    我们只需要配置nginx,在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可。这样,这个服务器上所有url都是相同的域 名、协议和端口。因此,对于浏览器来说,这些url都是同源的,没有跨域限制。而实际上,这些url实际上由物理服务器提供服务。这些服务器内的 javascript可以跨域调用所有这些服务器上的url。

    先下载nginx,然后将 nginx 目录下的 nginx.conf 修改如下:

    server {
    
        #nginx监听所有localhost:8080端口收到的请求
    	listen       8080;
    	server_name  localhost;
    
    	# Load configuration files for the default server block.
    	include /etc/nginx/default.d/*.conf;
    
        #localhost:8080 会被转发到这里
    	#同时, 后端程序会接收到 "192.168.25.20:8088"这样的请求url
    	location / {
    		proxy_pass http://192.168.25.20:8088;
    	}
    
    	#localhost:8080/api/ 会被转发到这里
        #同时, 后端程序会接收到 "192.168.25.20:9000/api/"这样的请求url
    	location /api/ {
    		proxy_pass http://192.168.25.20:9000;
    	}
    
    	error_page 404 /404.html;
    		location = /40x.html {
    	}
    
    	error_page 500 502 503 504 /50x.html;
    		location = /50x.html {
    	}
    }

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

    展开全文
  • iframe跨域解决方案

    2014-01-19 16:01:58
    在web开发中,跨域问题是经常遇到的,但是由于浏览器同源策略的限制,不同域之间属性和操作是无法直接交互的。本次讨论iframe和父页面的消息通信。
  • 9种常见的前端跨域解决方案(详解)

    千次阅读 多人点赞 2021-02-22 18:18:51
      在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。 什么是同源策略?   同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全...

    https://www.imooc.com/article/291931

    一、什么是跨域?

      在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。

    什么是同源策略?

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

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

    • Cookie、LocalStorage 和 IndexDB 无法读取
    • DOM和JS对象无法获得
    • 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
    不同域名不允许

    三、9种跨域解决方案

    1、JSONP跨域

      jsonp的原理就是利用<script>标签没有跨域限制,通过<script>标签src属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。

    1)原生JS实现:

     <script>
        var script = document.createElement('script');
        script.type = 'text/javascript';
    
        // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
        script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
        document.head.appendChild(script);
    
        // 回调执行函数
        function handleCallback(res) {
            alert(JSON.stringify(res));
        }
     </script>
    

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

    handleCallback({"success": true, "user": "admin"})
    

    2)jquery Ajax实现:

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

    3)Vue axios实现:

    this.$http = axios;
    this.$http.jsonp('http://www.domain2.com:8080/login', {
        params: {},
        jsonp: 'handleCallback'
    }).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 = querystring.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一种请求。

    2、跨域资源共享(CORS)

      CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
    它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
    CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

      浏览器将CORS跨域请求分为简单请求和非简单请求。

      只要同时满足一下两个条件,就属于简单请求

    (1)使用下列方法之一:

    • head
    • get
    • post

    (2)请求的Heder是

    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type: 只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain

    不同时满足上面的两个条件,就属于非简单请求。浏览器对这两种的处理,是不一样的。

    简单请求

      对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

    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...
    

      上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

    CORS请求设置的响应头字段,都以 Access-Control-开头:

    1)Access-Control-Allow-Origin:必选

      它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

    2)Access-Control-Allow-Credentials:可选

      它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

    3)Access-Control-Expose-Headers:可选

      CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。

    非简单请求

      非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

    预检请求

      预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。请求头信息里面,关键字段是Origin,表示请求来自哪个源。除了Origin字段,"预检"请求的头信息包括两个特殊字段。

    OPTIONS /cors HTTP/1.1
    Origin: http://api.bob.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: X-Custom-Header
    Host: api.alice.com
    Accept-Language: en-US
    Connection: keep-alive
    User-Agent: Mozilla/5.0..
    

    1)Access-Control-Request-Method:必选

      用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。

    2)Access-Control-Request-Headers:可选

      该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。

    预检请求的回应

      服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

      HTTP回应中,除了关键的是Access-Control-Allow-Origin字段,其他CORS相关字段如下:

    1)Access-Control-Allow-Methods:必选

      它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

    2)Access-Control-Allow-Headers

      如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

    3)Access-Control-Allow-Credentials:可选

      该字段与简单请求时的含义相同。

    4)Access-Control-Max-Age:可选

      用来指定本次预检请求的有效期,单位为秒。

    CORS跨域示例

    1)前端设置

    • 原生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({
        ...
       xhrFields: {
           withCredentials: true    // 前端设置是否带cookie
       },
       crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
        ...
    });
    

    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...');
    

    3、nginx代理跨域

      nginx代理跨域,实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin…等字段。

    1)nginx配置解决iconfont跨域

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

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

    2)nginx反向代理接口跨域

    跨域问题:同源策略仅是针对浏览器的安全策略。服务器端调用HTTP接口只是使用HTTP协议,不需要同源策略,也就不存在跨域问题。

    实现思路:通过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;
        }
    }
    

    4、nodejs中间件代理跨域

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

    1)非vue框架的跨域

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

    • 前端代码:
    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();
    
    • 中间件服务器代码:
    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...');
    
    

    2)vue框架的跨域

      node + vue + webpack + webpack-dev-server搭建的项目,跨域请求接口,直接修改webpack.config.js配置。开发环境下,vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以页面与代理接口之间不再跨域。

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

    5、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>
    

    1)子窗口:(http://child.domain.com/a.html)

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

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

    7、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.html)

      中间代理页,与a.html同域,内容为空即可。

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

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

    8、postMessage跨域

      postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:

    • 页面和其打开的新窗口的数据传递
    • 多窗口之间消息传递
    • 页面与嵌套的iframe消息传递
    • 上面三个场景的跨域数据传递

    用法:postMessage(data,origin)方法接受两个参数:

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

    9、WebSocket协议跨域

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

    1)前端代码:

    <div>user input:<input type="text"></div>
    <script src="https://cdn.bootcss.com/socket.io/2.2.0/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.'); 
        });
    });
    

    小结

      以上就是9种常见的跨域解决方案,jsonp(只支持get请求,支持老的IE浏览器)适合加载不同域名的js、css,img等静态资源;CORS(支持所有类型的HTTP请求,但浏览器IE10以下不支持)适合做ajax各种跨域请求;Nginx代理跨域和nodejs中间件跨域原理都相似,都是搭建一个服务器,直接在服务器端请求HTTP接口,这适合前后端分离的前端项目调后端接口。document.domain+iframe适合主域名相同,子域名不同的跨域请求。postMessage、websocket都是HTML5新特性,兼容性不是很好,只适用于主流浏览器和IE10+。

      这么多的跨域方案,没有最好,只有最合适的,根据具体的使用场景选择跨域方案。希望这篇博文能带给大家一点帮助~~

     

    作者:小铭子
    链接:https://www.imooc.com/article/291931
    来源:慕课网
    本文首次发布于慕课网 ,转载请注明出处,谢谢合作
    展开全文
  • iframe 跨域解决方法

    2019-04-10 01:04:03
    NULL 博文链接:https://hqlly.iteye.com/blog/1662337
  • 解决java项目跨域问题

    2019-05-29 15:52:01
    开发项目遇到了前端跨域问题,在网上试了很多的方法都不行,springboot的注解跨域解决也不行,在网上看来很多解决问题的办法,都很繁琐,最后从spring根源去寻找问题,最后从后台解决了前端的跨域问题,只需将此java...
  • tomcat跨域解决方案

    2012-08-13 20:35:38
    解决tomcat在IP 和端口不同时引起的跨域问题,解决方案,通过编写crossDomain.xml文件
  • springcloud gateway 跨域解决方案

    千次阅读 2021-02-14 10:38:51
    springcloud gateway 跨域解决方案问题验证解决方案 问题 springcloud gateway提供的自带的跨域过滤器有问题,前端还是会报跨域。zuul不会有这个问题。调试发现主要是游览器发送嗅探请求(OPTIONS)时,没有返回跨域...

    springcloud gateway 跨域解决方案

    问题

    springcloud gateway提供的自带的跨域过滤器有问题,前端还是会报跨域。zuul不会有这个问题。调试发现主要是游览器发送嗅探请求(OPTIONS)时,没有返回跨域的响应头,从而游览器报跨域问题。

    验证

    由于springcloud gateway为webflux与zuul不一样,同一个服务,采用spring内置的跨域过滤器,zuul可以通过而gateway报错。具体配置如下:

    1. gateway跨域配置
    spring:
      cloud:
        gateway:
          globalcors:
            cors-configurations:
              '[/**]':
                # 允许携带认证信息
                # 允许跨域的源(网站域名/ip),设置*为全部
                # 允许跨域请求里的head字段,设置*为全部
                # 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
                # 跨域允许的有效期
                allow-credentials: true
                allowed-origins: '*'
                allowed-headers: Content-Type,Content-Length, Authorization, Accept,X-Requested-With
                allowed-methods: '*'
                exposed-headers: Content-Type,Content-Length, Authorization, Accept,X-Requested-With
                max-age: 3600
    

    此配置无效,前端还是会报跨域问题,主要是前端发送OPTIONS请求时没有返回跨域信息

    1. zuul网关或者其它微服务servlet ,向容器中注入跨域过滤器
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.core.Ordered;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    /**
     * @author ZhouChuGang
     * @version 1.0
     * @project langangkj-commonm
     * @date 2020/5/4 12:24
     * @Description 跨域过滤器配置
     */
    @Slf4j
    @configuration
    @ConditionalOnMissingBean(CorsFilter.class)
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    public class CorsFilterConfiguration {
    
        public CorsFilterConfiguration() {
            log.info("==========注入跨域过滤器=============");
        }
    
        @Bean("corsFilter")
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration config = new CorsConfiguration();
            // #允许向该服务器提交请求的URI,*表示全部允许
            config.addAllowedOrigin(CorsConfiguration.ALL);
            // 允许cookies跨域
            config.setAllowCredentials(true);
            // #允许访问的头信息,*表示全部
            config.addAllowedHeader(CorsConfiguration.ALL);
            // 允许提交请求的方法,*表示全部允许
            config.addAllowedMethod(CorsConfiguration.ALL);
            source.registerCorsConfiguration("/**", config);
            return new CorsFilter(source);
        }
    
        @Autowired
        @Qualifier("corsFilter")
        private CorsFilter corsFilter;
    
        /**
         * 配置跨域过滤器
         */
        @Bean
        public FilterRegistrationBean<CorsFilter> corsFilterRegistration() {
            FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>();
            registration.setFilter(corsFilter);
            registration.addUrlPatterns("/*");
            registration.setName("corsFilter");
            registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
            return registration;
        }
    }
    

    此方案可以完美解决跨域问题。但是springcloud gateway 不是servlet 规范。

    解决方案

    1. gateway后面的微服务实现跨域。跨域由网关后面的服务实现。

    2. 实现一个过滤器,来做跨域允许。需要在响应头中加入以下信息

    # 这个为请求头中的 origin
    add_header 'Access-Control-Allow-Origin' '$http_origin' ;
    add_header 'Access-Control-Allow-Credentials' 'true' ;
    add_header 'Access-Control-Allow-Methods' 'PUT,POST,GET,DELETE,OPTIONS' ;
    add_header 'Access-Control-Allow-Headers' 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With' ;
    
    
    1. 采用nginx做代理,配置跨域响应头。(强烈推荐
      请求先到nginx,nginx再去请求gateway, 由nginx添加跨域响应头
    add_header 'Access-Control-Allow-Origin' '$http_origin' ;
    add_header 'Access-Control-Allow-Credentials' 'true' ;
    add_header 'Access-Control-Allow-Methods' 'PUT,POST,GET,DELETE,OPTIONS' ;
    add_header 'Access-Control-Allow-Headers' 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With' ;
    
    

    这里本人为了方便,采用第3中方案,测试完美解决

    展开全文
  • vue前端跨域解决方案

    千次阅读 2020-12-12 13:59:27
    为什么会出现跨域: 浏览器访问非同源的网址时,会被限制访问,出现跨域问题. 常见的跨域有三种: jspn跨域,原理:动态生成script标签,通过script标签引入接口地址(因为script标签不存在跨域的) cors跨域(后端开启)...
    为什么会出现跨域:

    浏览器访问非同源的网址时,会被限制访问,出现跨域问题.

    常见的跨域有三种:
    • jspn跨域,原理:动态生成script标签,通过script标签引入接口地址(因为script标签不存在跨域的)
    • cors跨域(后端开启) :全称 “跨域资源共享”,原理:它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
    • vue代理服务器proxy跨域:通过请求本地的服务器,然后本地的服务器再去请求远程的服务器(后端部署接口的服务器),最后本地服务器再将请求回来的数据返回给浏览器(本地服务器和浏览器之前不存在跨域)
      两个关键点:
      本地服务器(利用node.js创建的本地服务器进行代理,也叫代理服务器)和浏览器之间不存在跨域
      服务器和服务器之间不存在跨域
    话不多说,直接上代码:

    首先创建一个 vue.config.js文件

    // 假设要请求的接口是:http://40.00.100.100:3002/api/user/add
    module.exports = {
        devServer:{
          host:'localhost',  // 本地主机
            port:5000,  // 端口号的配置
            open:true,  // 自动打开浏览器
            proxy:{
              '/api': {   //  拦截以 /api 开头的接口
                target: 'http://40.00.100.100:3002',//设置你调用的接口域名和端口号 别忘了加http
                changeOrigin: true,    //这里true表示实现跨域
                secure: false, // 如果是https接口,需要配置这个参数
                pathRewrite: {
                  '^/api':'/'  //这里理解成用‘/api’代替target里面的地址,后面组件中我们掉接口时直接用api代替 比如我要调用'http://40.00.100.100:3002/api/user/add',直接写‘/api/user/add’即可
                }
              },
        // 假如又有一个接口是:http://40.00.100.100:3002/get/list/add
        // 那就再配置一个 get的,如下:
              '/get': {   //  拦截以 /get 开头的接口
                target: 'http://40.00.100.100:3002',//设置你调用的接口域名和端口号 别忘了加http
                changeOrigin: true,    //这里true表示实现跨域
                secure: false, // 如果是https接口,需要配置这个参数
                pathRewrite: {
                  '^/api':'/'  //这里理解成用‘/api’代替target里面的地址,
                }
              }
    			// 调用的时候直接  /get/list/add  就可以了
            }
        }
      }
    
      // 注意:修改了配置文件后一定要重启才会生效;
    

    我们可以利用axios的baseUrl直接默认值是 api,这样我们每次访问的时候,自动补上这个api前缀,就不需要我们自己手工在每个接口上面写这个前缀了
    在入口文件里面配置如下:

    import axios from 'axios'
    
    Vue.prototype.$http = axios
    axios.defaults.baseURL = 'api'  // 后面发现,其实不加这个感觉也好像可以
    
    如果这配置 'api/' 会默认读取本地的域
    

    如果只是开发环境测试,上面那种就足够了,如果区分生产和开发环境
    就需要如下配置

    分环境配置跨域:

    创建一个 api.config.js 文件(其实随便命名都可以)

    const isPro = Object.is(process.env.NODE_ENV, 'production')
    // 如果是生产环境,就用线上的接口;
    module.exports = {
        baseUrl: isPro ? 'http://www.vnshop.cn/api/' : 'api/'
    }
    

    然后在main.js 里面引入,这样可以保证动态的匹配生产和开发的定义前缀

    import apiConfig from './api.config'
    
    Vue.prototype.$http = axios
    import axios from 'axios'
    
    axios.defaults.baseURL = apiConfig.baseUrl
    

    经过上面配置后,在dom里面可以这样轻松的访问,也不需要在任何组件里面引入axios模块了

      async getData(){
            const res = await this.$http.get('/api/user/add');
            console.log(res);
        },
    

    小结:
    代理跨域的主要方式是利用服务器请求服务器的方式避过跨域问题来实现的.大概的流程: 浏览器===>代理服务器===>目标服务器.

    若有不对的地方,请不吝指出,同时也欢迎留言咨询,谢谢~

    展开全文
  • 2.安装跨域模块(一下代码修改都是在settings.dev下进行的) pip install django-cors-headers -i https://pypi.douban.com/simple 添加应用  INSTALLED_APPS = (  ...  'corsheaders',  ...  ) 中间件设置...
  • 主要介绍了详解ajax跨域问题解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • layer弹窗:top.layer弹窗到父页面跨域,通过postMessage方法将子页面的配置对象发送到父页面中,父页面再通过子页面的配置对象打开弹窗,对象内不能存在事件。
  • vue跨域解决的几种方案

    千次阅读 2020-09-03 16:02:38
    vue跨域解决的几种方案 一、开发环境解决跨域方法 平时使用vue开发的时候,大多会使用vue-cli搭建项目,在vue-cli搭建的项目中有一个配置文件vue.config.js,可以在该文件中进行相应的配置解决开发环境的跨域问题。 ...
  • 跨域解决方案

    2019-08-28 14:18:51
    本节课主要简介跨域解决方案 1.跨域是由浏览器安全策略引起的,所以可以将浏览器的跨域安全策略关掉,这主要是为了咱们测试 2.可以通过后端调用接口的方式,这样是不是就和咱们的浏览器调用没有关系了啊 3.可以通过...
  • 主要介绍了spring cloud gateway请求跨域问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • CORS ———— 跨域解决方案之二

    万次阅读 2018-10-11 18:05:11
    以下介绍CORS跨域解决方案 一、什么是CORS? CORS (Corss-Orign Resource Sharing) 是W3C工作草案,是一份浏览器技术的规范。定义了跨域资源访问时,浏览器和服务器之间如何通信,使用自定义的http头部允许浏览器...
  • 跨域解决方案(一)详细篇

    万次阅读 多人点赞 2019-03-28 12:12:02
    跨域问题在前端已经是老生常谈了,本文围绕着为什么产生跨域以及几种解决方案详细说明。 二、跨域起源 说到跨域不得不提到浏览器的同源策略(1995年,Netscape公司提出的,现在适用于所有浏览器),所谓同源策略,...
  • 本文给大家介绍了vue项目中跨域问题的完美解决方案,通过更改header,使用http-proxy-middleware 代理解决(项目使用vue-cli脚手架搭建),具体内容详情大家跟随脚本之家小编一起学习吧
  • Vue跨域解决方案

    千次阅读 2021-01-14 13:07:29
    二、解决跨域的办法 前言 跨域错误信息 Access to XMLHttpRequest at ‘http://192.168.2.92:3000/api/b/home’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Response to preflight ...
  • vue项目之跨域解决方案

    千次阅读 2020-05-15 00:08:51
    跨域常见解决方案 jsonp (项目基本不用) 原理:动态生成script标签,通过src属性加载 缺点:不支持POST请求,支持get请求 应用场景:有些第三方数据接口可能会使用jsonp解决跨域问题,工作中不怎么用。 中间...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 131,321
精华内容 52,528
关键字:

跨域解决