转载链接:
https://juejin.im/post/5e8158e1e51d45470d5269af
导论
随着RESTful架构风格成为主流,以及Vue.js、React.js和Angular.js这三大前端框架的日益强大,越来越多的开发者开始由传统的MVC架构转向基于前后端分离这一基础架构来构建自己的系统,将前端页面和后端服务分别部署在不同的域名之下。在此过程中一个重要的问题就是跨域资源访问的问题,通常由于同域安全策略浏览器会拦截JavaScript脚本的跨域网络请求,这也就造成了系统上线时前端无法访问后端资源这一问题。笔者将结合自身开发经验,对这一问题产生的原因以及相应的解决方案,给出详细介绍。
问题原因
同源策略
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指:协议、域名、端口相同。
一个浏览器的两个tab页中分别打开来百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。
现象分析
在前端开发阶段,一些框架的脚手架工具会使用webpack-dev-serve来代理数据请求,其本质上是一个基于node.js的网页服务器,所以感受不到跨域资源访问的限制。
当网站上线后,网页上很多资源都是要通过发送AJAX请求向服务器索要资源,但是在前后端分离的系统架构中,前端页面和后端服务往往不会部署在同一域名之下。比如用户通过浏览器访问 www.test001.com 这一地址,来到了系统首页,此时浏览器从网站服务器中只取回了基本的HTML页面以及CSS样式表文件和JavaScript脚本。系统首页的其他内容,比如轮播图、文章列表等,需要利用JavaScript脚本程序,向地址为 www.test002.com 的后端应用服务器发送请求来获取信息。此时由于浏览器的同源策略,该请求会被浏览器所拦截,这就造成了前后端数据不通这一结果。
解决方案
前端解决方案
反向代理
因为由于浏览器的同源策略,JavaScript脚本程序只能向同一域名下的服务器发送网络请求,那么可以通过网页服务器转发这一网络请求到相应的后端服务器,获取相关数据,然后网页服务器再把这一数据返回给浏览器。这一过程称之为反向代理。
假设用户通过地址www.test001.com访问到了系统首页,该系统首页中所加载的JavaScript脚步程序本应该要发送AJAX请求到
www.test002.com/api/article…这一地址,来获取首页文章列表信息。此时应该改成向
www.test001.com/api/article…这一与之同源的地址发送数据请求。该系统的网页服务器会收到此请求,然后代替JavaScript脚本程序向
www.test002.com/api/article…这一地址请求数据,获取数据后将之返回给浏览器。此时JavaScript脚本程序就通过网页服务器这一桥梁成功获取到了后端应用服务器上的数据。
若服务器采用了宝塔面板这一管理软件,可以直接通过其提供的可视化界面进行反向代理的设置。对于一些新手而言,直接面对命令行进行各种操作,不够直观且难度较高,此时采用一些可视化的服务器管理软件是一个不错的选择。
若是喜欢用vim 直接在命令行里修改的同学可以参考这篇博客
这个解决方案是不是有些眼熟呢?
JSONP跨域
浏览器的同源策略对JavaScript脚本向不同域的服务器请求数据进行了限制,但是没有对HTML中的 复制代码
在这里值得注意的是,因为请求数据的接口地址是写在了