精华内容
下载资源
问答
  • 9种常见的前端跨域解决方案(详解)
    千次阅读 多人点赞
    2021-02-22 18:18:51

    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
    来源:慕课网
    本文首次发布于慕课网 ,转载请注明出处,谢谢合作
    更多相关内容
  • 正常使用AJAX会需要正常考虑跨域问题,所以伟大的程序员们又折腾出了一系列跨域问题的解决方案,如JSONP、flash、ifame、xhr2等等。本文给大家介绍JS跨域解决方案之使用CORS实现跨域,感兴趣的朋友参考下吧
  • 主要介绍了vue-cli3 中跨域解决方案,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
  • 前后端分离H5 跨域解决方案 提供多种解决方法 详情请下载文件 自己看 100%可以解决你的问题
  • 主要介绍了前端常见跨域解决方案的相关内容,包括对跨域的解释,常见跨域场景以及跨域解决方案,内容丰富,需要的朋友可以参考下。
  • Nodejs Express Ajax跨域请求实例代码,Nodejs Express Ajax跨域请求实例代码
  • 跨域解决方案

    2019-08-28 14:18:51
    本节课主要简介跨域解决方案 1.跨域是由浏览器安全策略引起的,所以可以将浏览器的跨域安全策略关掉,这主要是为了咱们测试 2.可以通过后端调用接口的方式,这样是不是就和咱们的浏览器调用没有关系了啊 3.可以通过...
  • 分享转载:前端常见跨域解决方案 1、 通过jsonp跨域 2、 document.domain + iframe跨域 3、 location.hash + iframe 4、 window.name + iframe跨域 5、 postMessage跨域 6、 跨域资源共享(CORS) 7、 nginx...
  • Javascript 跨域访问解决方案 在客户端编程语言中 如 javascript 和 ActionScript 同源策略是一个很重要的安全理念 它在保证数据的安全性方面有着重要的意义同 源策略规定跨域之间的脚本是隔离的一 个域的脚本不能...
  • 本文通过设置Access-Control-Allow-Origin来实现跨域。 例如:客户端的域名是client.runoob.com,而请求的域名是server.runoob.com。 如果直接使用ajax访问,会有以下错误: XMLHttpRequest cannot load ...
  • NULL 博文链接:https://sun123start.iteye.com/blog/2150778
  • 前端跨域解决方案

    2017-10-12 11:29:53
    前端跨域解决方案,jsonp和cros两种解决方式。我们发现,Web页面上调用js文件时不受是否跨域的影响,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如[removed]、、<iframe>。那就是说如果要跨域访问数据,...
  • 关于跨域,有N种类型,本文只专注于ajax请求跨域(,ajax跨域只是...o表现(整理了一些遇到的问题以及解决方案) 如何解决ajax跨域 oJSONP方式 oCORS方式 o代理请求方式 如何分析ajax跨域 ohttp抓包的分析 o一些示例
  • 通过XMLHTTPRquest请求不同域上的数据,原来js跨域访问是后台有个处理路径“/test”的函数。下面给大家介绍jQuery跨域问题解决方案,有需要的小伙伴可以参考下
  • js跨域解决方案

    2013-06-25 15:31:11
    js跨域解决方案
  • java跨域解决方案

    2021-06-09 15:01:52
    /** * 跨域 */ @Configuration public class GulimallCorsConfiguration { @Bean // 添加过滤器 public CorsWebFilter corsWebFilter(){ // 基于url跨域,选择reactive包下的 UrlBasedCorsConfigurationSource ...

    ​​​​​​​

     

    package com.atguigu.gulimall.gateway.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.reactive.CorsWebFilter;
    import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
    
    /**
     * 跨域
     */
    @Configuration
    public class GulimallCorsConfiguration {
        @Bean // 添加过滤器
        public CorsWebFilter corsWebFilter(){
            // 基于url跨域,选择reactive包下的
            UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
            // 跨域配置信息
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            // 允许跨域的头
            corsConfiguration.addAllowedHeader("*");
            // 允许跨域的请求方式
            corsConfiguration.addAllowedMethod("*");
            // 允许跨域的请求来源
            corsConfiguration.addAllowedOrigin("*");
            // 是否允许携带cookie跨域
            corsConfiguration.setAllowCredentials(true);
    
            // 任意url都要进行跨域配置
            source.registerCorsConfiguration("/**",corsConfiguration);
            return new CorsWebFilter(source);
        }
    
    }
    

     

    展开全文
  • 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 ...

    前言

    跨域错误信息

    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 request doesn’t pass access control check: It does not have HTTP ok status.
    在这里插入图片描述

    一、跨域是什么?

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

    #协议跨域
    http://a.baidu.com 访问 https://a.baidu.com;
    #端口跨域
    http://a.baidu.com:8080 访问  http://a.baidu.com:80;
    #域名跨域
    http://a.baidu.com  访问  http://b.baidu.com;
    

    二、解决跨域的办法

    1.这里以使用vue脚手架生成的标准项目为准。一般在项目config目录下面有个index文件

    module.exports = {
        publicPath: './',
        lintOnSave: true,
        configureWebpack: {
            //关闭 webpack 的性能提示
            performance: {
                hints:false
            }
        
        },
        devServer: {
            proxy: {
                '/api': {
                    target: 'http://192.168.2.90:3000',//后端接口地址
                    changeOrigin: true,//是否允许跨越
                    pathRewrite: {
                        '^/api': '/api'//重写,
                    }
                }
            }
        }
    }
    

    此方法只能在开发环境中使用。
    后端请求地址是http://192.168.92.2:3000,所有api的接口url都以/api开头。
    所以首先需要匹配所有以/api开头的.然后修改target的地址为http://192.168.2.92:9090。
    最后修改pathRewrite地址:将前缀’^api’转为’/api’。
    如果本身的接口地址就有’/api’这种通用前缀,就可以把pathRewrite 删掉。

    2.配置一下axios.defaults.baseURL = '/api’这样就可以保证动态的匹配生产和开发环境的定义前缀,代码如下:

    // mock服务器
    axios.defaults.baseURL ='/api';
    

    3.重新启动项目,发现解决了跨域问题
    在这里插入图片描述

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

    热门讨论 2012-08-13 20:35:38
    解决tomcat在IP 和端口不同时引起的跨域问题,解决方案,通过编写crossDomain.xml文件
  • JSONP, JSON with Padding,是前端解决跨域方案, 利用`<script>` 的src没有跨域限制的例外来实现跨域访问

    JSONP, JSON with Padding,是前端解决跨域的方案,  利用<script> 的src没有跨域限制的例外来实现跨域访问。

    跨域禁止的模拟示例

    • 安装两个tomcat, 端口分别是8080和9090
    • 在两个tomcat 的webapps下分别创建一个应用目录"jsonp",在8080端口的页面访问9090端口的页面, 因为端口不同, 属于跨域状况。
      步骤:
    1. 在8080端口创建jsonp目录, 在该目录创建index.html, 内容如下:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
      <meta http-equiv="content-type" content="text/html; charset=utf-8">
      <title>JSONP</title>
      <script  type="text/javascript">
        function handleClick(){
    
           var url = "http://localhost:9090/jsonp/index.jsp";
           var xhr = new XMLHttpRequest();
           xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                        alert( xhr.responseText );
                }
            };
            xhr.open('get', url, true);
            xhr.send(); 
        }
      </script>
      </head>
      <body>
          <button id="btn" onclick="handleClick()">Click Me</button>
      </body>
    </html>
    
    

    在该页面中,点击按钮使用Ajax调用9090的某个页面。

    1. 在9090端口创建jsonp目录, 在该目录创建index.jsp, 内容如下:
    <%
         String callbackfunc = request.getParameter("callbackfunc");
         out.print(callbackfunc+"([{ name:'Oscar999',age:'18'}]);");
         out.flush();
    %>
    
    

    这里的jsp页面返回一个字符串。

    1. 运行的效果如下:
      在这里插入图片描述

    如预期, 因为跨域,所以不能访问。

    JSONP的解决示例

    因为<script> 的src没有跨域限制,将8080端口的index.html 修改如下:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
      <meta http-equiv="content-type" content="text/html; charset=utf-8">
      <title>JSONP</title>
      <script type="text/javascript">  
        function myCallBackFunc(result){   
           alert(result[0].name);   
        }   
        </script>
        <script type="text/javascript" src="http://localhost:9090/jsonp/index.jsp?callbackfunc=myCallBackFunc"></script>
      </head>
      <body>
      </body>
    </html>
    
    

    因为http://localhost:9090/jsonp/index.jsp?callbackfunc=myCallBackFunc 返回的字符串是myCallBackFunc([{ name:'Oscar999',age:'18'}]);, 所以上面的

    <script type="text/javascript" src="http://localhost:9090/jsonp/index.jsp?callbackfunc=myCallBackFunc">
    </script>
    

    其实也就等效于:

    <script type="text/javascript">
    myCallBackFunc([{ name:'Oscar999',age:'18'}]);
    </script>
    

    myCallBackFunc()这个函数是在index.html定义的一个函数, 上面的JavaScript代码其实就是用后端返回的JSON格式数据作为参数, 执行这个函数, 执行的效果如下:

    在这里插入图片描述

    本篇示例代码和环境

    本篇演示的环境和示例代码可以到以下地址下载:

    https://download.csdn.net/download/oscar999/83976534

    步骤是:
    1. 解压上面压缩档
    2. 进入tomcat9-1的bin目录,点击startup.bat启动服务器1
    3. 进入tomcat9-2的bin目录,点击startup.bat启动服务器2
    4. 进入 http://localhost:8080/jsonp/index.html 演示跨域访问禁止
    5. 进入http://localhost:8080/jsonp/index2.html 演示JSONP实现跨域访问

    展开全文
  • 主要介绍了NODE.JS跨域问题的完美解决方案,非常不错具有参考借鉴价值,需要的朋友可以参考下
  • Ajax跨域访问解决方案

    2019-04-01 01:09:29
    NULL 博文链接:https://exceptioneye.iteye.com/blog/1405495
  • 2.安装跨域模块(一下代码修改都是在settings.dev下进行的) pip install django-cors-headers -i https://pypi.douban.com/simple 添加应用  INSTALLED_APPS = (  ...  'corsheaders',  ...  ) 中间件设置...
  • 前端跨域解决方案汇总

    千次阅读 2020-12-20 13:43:38
    编者注:关于跨域的文章,之前分享过很多,来看看这篇前端跨域解决方案,由简及深介绍各种存在的跨域请求解决方案,包括 document.domain, location.hash, window.name, window.postMessage, JSONP, WebSocket, CORS...
  • 主要介绍了跨域解决方案Jsonp原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 前端跨域原理以及跨域解决方案.docx
  • 一、为什么会出现跨域问题 出于浏览器的同源策略限制。同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源...
  • laravel 跨域解决方案

    2022-02-14 14:17:31
    借鉴:laravel 跨域解决方案 - 归一山人 - 博客园 自己 1.新建一个中间件 php artisan make:middleware EnableCrossRequestMiddleware 2、书写中间件内容 <?php namespace App\Http\Middleware; use ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 59,433
精华内容 23,773
关键字:

跨域解决方案