前后端分离实践总结 | 跨域请求的那些事儿
一、前言
关于前后端分离的概念,之前个人的理解主要停留在开发模式上的分离,而实际上要真正实现前后端完全分离还需要涉及部署环境的分离,所有此处介绍的前后端分离应该是web应用的一种架构模式。
如图,在传统架构模式中,前后端代码存放于同一个代码库中,甚至是同一工程目录下。页面中还夹杂着后端代码。前后端工程师进行开发时,都必须把整个项目导入到开发工具中(当前我们微信提现的项目就是属于此类)。
而前后端分离模式在代码组织形式上有以下两种:
半分离:前后端共用一个代码库,但是代码分别存放在两个工程中。后端不关心或很少关心前端元素的输出情况,前端不能独立进行开发和测试,项目中缺乏前后端 交互的测试用例。
分离 :前后端代码库分离,前端代码中有可以进行Mock测试(通过构造虚拟测试对象以简化测试环境的方法)的伪后端,能支持前端的独立开发和测试。而后端代码中除了功能实现外,还有着详细的测试用例,以保证API的可用性,降低集成风险。
二、实践
以此次喵盟项目从 前后端半分离 到 前后端分离 改造的实践为例,做以下要点总结。
1、请求url映射配置
由于之前前后端代码放在同一代码库中,前端请求服务的url直接取自当前路径即可。但分离之后,前端请求需要进行跨域请求,根据不同的域名发送对应的url。
当前喵盟域名配置如下:
'm.dm.com': {
baseUrl: 'http://meng.dm.com/',
domain: '.dm.com'
},
'testm.youximao.cn': {
baseUrl: 'http://testmeng.youximao.cn/',
domain: '.youximao.cn'
},
'testm2.youximao.cn': {
baseUrl: 'http://testmeng2.youximao.cn/',
domain: '.youximao.cn'
},
'm-pre.youximao.tv': {
baseUrl: 'http://meng-pre.youximao.tv/',
domain: '.youximao.tv'
},
'm.youximao.tv': {
baseUrl: 'https://meng.youximao.tv/',
domain: '.youximao.tv'
}
2、支撑CORS跨域前端基础配置
完成第一步之后,当页面在 m.dm.com 中去请求 meng.dm.com 的时候,我们会不出意料的被浏览器的同源策略所阻止,所以此时我们通过CORS这位大佬来完美规避同源策略(JSNOP那位大佬只支持GET请求,故弃之)。
CORS是什么鬼?
当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如m.youximao.tv),那么我们就可以认为它们是相同的域(协议,域名,端口都必须相同)。跨域就指着协议,域名,端口不一致,出于安全考虑,跨域的资源之间是无法交互的。
CORS(Cross-Origin Resource Sharing, 跨源资源共享)是W3C出的一个标准,其思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。因此,要想实现CORS进行跨域,需要服务器进行一些设置,同时前端也需要做一些配置和分析。
好了,接下来该是我们前端要做的一些事情:
好像也就html中加一句话。。。
<!-- 允许跨域请求 start-->
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<!-- 允许跨域请求 end-->
如果前端模拟后端响应的话,可在对应的res中做如下配置:
// DEFAULT ALLOW CORS
res.setHeader('Access-Control-Allow-Origin', '*') // 允许跨域访问的域名
res.setHeader('Access-Control-Allow-Methods', '*') // 允许跨域请求的方法
3、跨域传递cookie
完成第二步之后,我们会发现登录请求的确OK了,但是登录之后就懵逼了,页面显示异常,查看原因之后发现浏览器本地的cookie的确有了,但是后端服务并没有获取到!
默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。
前端关键代码:
如图,在请求上加个 withCredentials: true 即可。
当然,这只是前端打开一个开口而已,后端做的事情可就多了。
如图,后端服务在进行跨域处理的时候,需要将 Access-Control-Allow-Credentials 设为 true 即可。
原理:
以上前后端设置的ture属性(withCredentials、Access-Control-Allow-Credentials),都是允许跨域发送cookie的一个开关设置,需要前后端都做到打开模式。
踩过的坑:
在以上axios公用请求方法中配置好之后,也会有些不调用公用请求function的漏网之鱼,我们也需要对其及时加上相应的允许传cookie配置!
<el-upload name="file" :with-credentials="true" :action="baseUrl + 'web/common/upload' + suffix" :show-file-list="false" :on-progress="progressIdCard1" :on-success="uploadIdCard1" :before-upload="beforeIdCard1">
上传
</el-upload>
以上代码为当前项目中的上传组件,该请求是自动触发的,需要添加 :with-credentials="true" 来支持cookie跨域传递
三、总结
通过这次项目前后端完全分离的改造,提升了自己对项目部署的认知,以及对请求头(request headers)和响应头(response headers)各参数有了更深刻的接触和理解。
(ps: 前后端分离之后最爽就是index.html又回到自己的手上了,哈哈哈,要想偷懒加个cdn资源可以直接往html头部引入即可。)
参考资料:CORS——跨域请求那些事儿