前端跨域及本地代理

2,121 阅读4分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。

跨域是前后端联调老生常谈的问题了,今天来简要概括一下关于前端跨域方法以及本地如何代理。

什么是跨域

首先是因为浏览器有同源策略 Same origin policy ,简单来说就是不允许不同host、端口或者协议不同的网页获取另外一个域名下的资源。不同源的定义是, host、 端口、协议(http vs https)不同就算不同源,前端俗称的跨域简单来说一个域去另外一个域下获取资源。

前端跨域的方法

  1. 使用本地代理服务器(手脚架插件,Node插件等),不走浏览器就没有同源策略机制也就不会触发跨域检测; 这也就为什么用postman时不会触发跨域报错;

  2. Nginx反向代理,类似本地代理服务器,不过是在目标服务器上做的转发;

  3. postMessage:相同浏览器页面之间跨域,通过postMessage指定域名跟目标域监听message消息发跟接收消息;

  4. iframe+location.hash: 相同浏览器页面之间跨域,a想要跨域与b通信,通过同源中间页c,a加载b的iframe 利用hash传值,b再同理把回应再传向c,c可以访问a页面所以对象从而将回应传递给a;

  5. iframe+window.name: 创建一个代理域的iframe,利用iframe的src属性加载外域,然后将外域的window.name保存在代理域,本地域获取到代理域的window.name之后销毁代理域,保证数据不被其他域获取的同时实现window.name从外域传递到本地域;

  6. iframe+document.domain,主要是相同主域名,主子窗口页面强行修改document.domain实现与主窗口同源;

  7. Jsonp:通过script标签发起get请求,服务器接收请求解析前端传去过去的回调,并把数据传入该回调;

  8. 其他协议例如Websocket。

其中3,4,5,6都属于使用Bom API来实现跨域,所以只能实现页面之间的跨域,适合同一站点的外链页面与主页面直接的通信等。从前后端接口请求的方面来看,让后端去设置服务器CORS接口,触发CORS流程才是王道(减少前端工作量),了解更多可以查看 跨域资源共享

不成熟观点:从接口请求层面看纯前端跨域根本就是伪命题,没有服务器设置CORS根本很难绕过同源机制(越容易就越不安全)。

本地代理流程

当我在a.com 想调部署在b.com(服务器未CORS处理)下的接口时,浏览器会阻止我并向我丢过一个COR error:Access to XMLHttpRequest at 'target.com' from origin 'http://localhost:8001' has been blocked by CORS policy.

以Vue cli为例子,在vue.config.js 里的devServer加上

  proxy: {      '/api': {        target: 'b.com',        changeOrigin: true,        pathRewrite: {          '/api': '',        },    }

然后再在请求里加上比如 要请求 b.com/list axios.get('api/list') 就可以成功请求。

原理:当发起请求时,浏览器会把请求发到代理服务器,然后代理服务器会把就会把请求改成 b.com/list发给b.com的服务器, 跨域的本质是ajax引擎的拦截 ,不走ajax引擎也就不会拦截。

小插曲

今天联调时,我想修改请求头里的origin时,发现怎么改origin 都还是localhost

 proxy: {      '/api': {        target: 'b.com',        changeOrigin: true,        pathRewrite: {          '/api': '',        },        onProxyReq: function (request) {          request.setHeader('origin', 'b.com')        },      }, }

我以为onProxyReq的事件没触发, 就带着疑惑去搜,看了答案之后知道 在vue-cli 3.0配置proxy的onProxyReq事件没有触发 。本地代理服务器的过程,是localhost浏览器发请求到代理服务器,代理服务器修改请求头origin,再去发给b.com, 然后真实服务器再返回请求给浏览器。中间商赚没赚到差价控制台是看不见的。

总结

本地代理服务器是开发阶段比较常用的手段,线上环境还是需要服务器去设置CORS。