自动接触前端,跨域这个词就一直萦绕在耳畔。由于通常接手的项目都已经作好了这方面的处理,并且以前一直感受对这方面模棱两可,因此今天就抽个时间梳理一下。javascript
跨域这个概念来自一个叫 “同源策略” 的东西。同源策略是浏览器(注意是浏览器,跟通讯协议无关)上为了安全考虑实施的很是重要的安全机制。html
Ajax
默认只能获取到同源的数据,对于非同源的数据,Ajax是获取不到的。前端
- 协议相同
- 域名相同
- 端口相同
举例来讲,http://www.example.com/dir/page.html
这个网址,协议是http://
,域名是www.example.com
,端口是80
(默认端口能够省略)。这个网址,在这个地址中要去访问下面服务器的数据,那么会发生什么状况呢?vue
URL | 结果 | 缘由 |
---|---|---|
https://www.example.com/dir/other.html |
不一样源 | 协议不一样,https 和 http |
http://en.example.com/dir/other.html |
不一样源 | 域名不一样 |
http://www.example.com:81/dir/other.html |
不一样源 | 端口不一样 |
http://www.example.com/dir/page2.html |
同源 | 协议,域名,端口都相同 |
http://www.example.com/dir2/page.html |
同源 | 协议,域名,端口都相同 |
那么。想要获取非同源地址的数据,就要使用跨域。不管是 Ajax 仍是跨域,都是为了访问服务器的数据。简单的来讲, Ajax 是为了访问本身服务器的数据,跨域是为了访问别人服务器的数据(好比获取天气信息,航班信息等)。java
为了保证用户信息的安全,防止恶意的网站窃取数据。node
“ 设想这样一种状况:A网站是一家银行,用户登陆之后,又去浏览其余网站。若是其余网站能够读取A网站的 Cookie,会发生什么?webpack
很显然,若是 Cookie 包含隐私(好比存款总额),这些信息就会泄漏。更可怕的是,Cookie 每每用来保存用户的登陆状态,若是用户没有退出登陆,其余网站就能够冒充用户,随心所欲。由于浏览器同时还规定,提交表单不受同源政策的限制。git
因而可知,"同源政策"是必需的,不然 Cookie 能够共享,互联网就毫无安全可言了。”github
via@ 阮一峰web
- 反向代理
- JSONP
- WebSocket
- CORS(根本解决方案)
反向代理就是使用本身的服务器,在后端请求目标服务器的数据,而后返回给客户端。至关于作了一把中间人的感受。
反向代理服务器,最经常使用的就是Nginx
。可是做为前端代码实现的Node.js
也能够搭建反向代理服务器。
下面来简要介绍使用node服务进行反向代理。
要实现这个前提是,前端开发环境必须运行在nodejs服务中,所幸的是,如今前端的开发自动化工具都是创建在nodejs上的,因此这个前提也不是很重要。
好比我有一个后端接口:http://39.105.136.190:3000/zhuiszhu/goods/getList
,能够获取一些商品列表数据,可是我运行的node项目是在 localhost:3000
下的,明显构成跨域。
咱们根据项目使用的框架不一样,处理的方式也不一样。
若是是express项目,可使用http-proxy-middleware
来处理,这个插件主要用于将前端请求代理到其它服务器。
用法很简单。你能够参考插件github官网: https://github.com/chimurai/http-proxy-middleware
首先须要在你的express项目中安装该插件:
npm install --save-dev http-proxy-middleware
而后在 app.js
中进行代理设置(示例以下):
var express = require('express'); var proxy = require('http-proxy-middleware'); var app = express(); app.use('/zhuiszhu', proxy({target: 'http://39.105.136.190:3000/', changeOrigin: true})); app.listen(3000);
以后再项目中再次发送ajax请求的时候,能够看到数据能够收到了。
$.ajax({ url: '/zhuiszhu/goods/getList', type: 'GET', success(res) {}, });
咱们常常在vue开发项目的时候,会用webpack做为前端自动化构建工具的话,也会使用到webpack-dev-server
的插件,那么能够引用webpack-dev-server
来进行配置跨域方案。
webpack-dev-server是一个小型的nodejs服务器,是基于express框架的,用于实时监听和打包编译静态资源。其中里面有一个属性是proxy,是专门来配置代理请求接口的。
你只须要在webpack.config.js
中 devServer
中以下设置便可:
devServer: { port: 3000, inline: true, proxy: { "/zhuiszhu": { target: "http://39.105.136.190:3000/", changeOrigin: true //必须配置为true,才能正确代理 } } },
其实能够看出, webpack 的 devServer.proxy 就是使用了很是强大的 http-proxy-middleware 包来实现代理的,因此本质上是相通的。
JSONP基本思想是,网页经过添加一个<script>
元素,向服务器请求JSON数据,这种作法不受同源政策限制;服务器收到请求后,将数据做为参数放在一个指定名字的回调函数里传回来,这个回调函数的名字咱们须要经过js定义好。
好比:当页面资源加载完毕时候,获取跨域的数据,而且制定回调函数的名字为foo
:
window.onload = function () { var script = document.createElement("script"); script.setAttribute("type","text/javascript"); script.src = "http://bbb.com?callback=foo; document.body.appendChild(script); }; foo(data) { console.log(data); // data即为跨域获取到的数据 }
在服务器那边,须要将数据放入foo函数的参数中:
foo('hello world')
使用JSONP须要注意:
- 必须后端配置相应回调函数。
- 只能发送
GET
请求。
WebSocket是一种通讯协议,使用ws://
(非加密)和wss://
(加密)做为协议前缀。该协议不实行同源政策,只要服务器支持,就能够经过它进行跨源通讯。
因为发出的WebSocket请求中有有一个字段是Origin
,表示该请求的请求源(origin),即发自哪一个域名。
正是由于有了Origin
这个字段,因此WebSocket才没有实行同源政策。由于服务器能够根据这个字段,判断是否许可本次通讯。
CORS全称“ Cross-origin resource sharing ”(跨域资源共享),相比JSONP, CORS容许任何类型的请求 。
CORS须要浏览器和服务器同时支持。目前,全部浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通讯过程,都是浏览器自动完成,不须要用户参与。对于开发者来讲,CORS通讯与同源的AJAX通讯没有差异,代码彻底同样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受。
所以,实现CORS通讯的关键是服务器。只要服务器实现了CORS接口,就能够跨源通讯。
综上,若是访问的别人服务器的资源,而且未设置JSONP,也未开放WebSocket白名单,也没有设置CORS接口,那么惟一的选择就是使用本身的服务器进行反向代理。
本文完。
(啾咪 ^.<)