雨涵
文章6
标签13
分类0
前端跨域问题

前端跨域问题

在项目中遇到前端跨域问题,便去了解一下跨域的原因,并总结了几个常用解决方案,便写下这篇博文以作记录。


何为跨域?

以下是引用wiki百科的解答,您可以花几分钟好好读一下。

跨域资源共享(英语:Cross-origin resource sharing,缩写:CORS),用于让网页的受限资源能够被其他域名的页面访问的一种机制。[1]

通过该机制,页面能够自由地使用不同源(英语:cross-origin)的图片、样式、脚本、iframes以及视频。[2]一些跨的请求(特别是Ajax)常常会被同源策略(英语:Same-origin policy)所禁止的。跨源资源共享定义了一种方式,为的是浏览器和服务器之间能互相确认是否足够安全以至于能使用跨源请求(英语:cross-origin requests)。[3]比起纯粹的同源请求,这将更为自由和功能性的(functionality ),但比纯粹的跨源请求更为安全。

跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略[4]

wiki百科上面的介绍比较的晦涩,让人摸不着头脑,广义来说跨域即是一个域请求另一个域的资源

广义的跨域:

1.资源跳转:重定向、表单提交、A链接。

2.资源嵌入:<script>、<frame>、<img>、<link>等dom标签,css中的background : url( )等文件。

3.脚本请求:js发送的aiax请求、dom和js对象的跨域操作等。

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

什么是同源策略?

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

同源策略主要限制ajax请求不能发送,重点在于“协议+域名+端口”,即只有三者完全相同才可通信,否则则被限制。

常见前端跨域解决方案:

1.JSONP解决

由于<script>标签没有跨域限制,通过<script>标签src属性,发送带有callback参数的get请求,服务端将接口数据放入callback函数中,返回给浏览器解析展示。

原生js实现

1
2
3
4
5
6
7
8
9
10
11
12
13
<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>

``

注意解析一定要用JSON.stringfy

2.nodejs中间件代理跨域

​ 我最开始想到的方法,node充当中间件,通过代理服务器实现数据转发。分为两种情况:

1.非vue框架跨域:

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

  • 前端代码:
    1
    2
    3
    4
    5
    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
    xhr.send();
    zhoizho
  • 中间件代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var express = require('express');
    var proxy = require('http-proxy-middleware');
    var app = express();
    app.use('/', proxy({
    target: 'http://www.domain2.com:8080',
    changeOrigin: true,

    onProxyRes: function(proxyRes, req, res) {
    res.header('Access-Control-Allow-Origin', 'http://www.domain1.com');
    res.header('Access-Control-Allow-Credentials', 'true');
    },
    cookieDomainRewrite: 'www.domain1.com'
    }));

    app.listen(3000);
    console.log('Proxy server is listen at port 8000...');

2.vue框架下解决

​ vue+webpack已经提供了现成的解决方案–webpack-dev-server,

但该解决方案只适合开发版本!!!

Webpack.config.js-dev代码:
1
2
3
4
5
6
7
8
9
devServer: {
historyApiFallback: true,
proxy: [{
context: '/login',
target: 'http://www.domain2.com:8080',
changeOrigin: true,
secure: false,
cookieDomainRewrite: 'www.domain1.com'
}],

以上就是这次所说的解决方案,当然方案还有很多,毕竟学无止境哈哈哈,以后再面对不一样的业务场景用到了其他方法再慢慢补充。

本文作者:雨涵
本文链接:https://guangyuzhan.github.io/posts/null/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可