[Re] 表示在服务器出问题之前就写过的文章,被重新上线或重新编辑的相同话题
跨域
浏览器的安全机制不允许跨域请求。但在前后端分离的研发流程中,后端和前端显然不是,也不会是同一个域。这种时候就产生了跨域
同源和跨域
以下情况会产生跨域问题:
所以“同源”实际上指的是协议、域名、端口要一致。任何一种不同都会产生“跨域”。
非同源限制
在非同源的情况下,浏览器出于安全和网站隔离等原因的考虑,会出现不少问题:
例如,cookie、localStorage 和 indexedDB 是无法非同源获取的。
同时,无法向非同源地址发送 AJAX 请求,也无法接触非同源网页的 DOM。
以上问题都是所谓的“跨域”问题。
需跨域的场景
单点登录
一个大型网站,不同功能可能需要不同的的子域,但是他们都在同一个主域下,需要共享登录状态(例如淘宝的登录域名和主要业务域名不在一个子域下)。
这种情况需要完成单点登录
跨域异步请求(研发阶段)
前后端分离的浏览器端异步请求会被浏览器机制挡在门外,这种情况需要处理请求问题。
解决
跨域问题是可以通过一些技术手段解决的。
单点登录
登录状态我们通常会存在只有 4kb 空间的 cookie 里,但非同源时无法共享登录状态。
由于浏览器是通过 document.domain 属性来检查两个页面是否同源的。这时候如果我们手动设置相同的属性,既可以解决无法读取非同源网页的 Cookie问题。
// 在入口文件
document.domain = 'mitkimi.com'
异步请求(AJAX API)
异步请求跨域是最常见的跨域问题。我们说的“跨域问题”一般情况不特指的情况下也指的是这种情况。解决跨域请求问题有很多种方法。
由于有些方法不能达到很好的通用效果,所以这里仅介绍通用的解决方法或对于其他方法一带而过
CORS
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
- 普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
- 带cookie跨域请求:前后端都需要进行设置
Access-Control-Allow-Origin 属性可以设置为 * 表示所有人都可以跨域请求,也可以设置为指定的域名进行请求。
当设置了 Access-Control-Allow-Origin 属性后有一个致命的问题,即设置为 * 时,所有人都可以调通,也就是说所有人都可以使用这个项目。安全性就没有办法保障。
即便是把 Access-Control-Allow-Origin 属性设置为指定的域名依旧无法保障安全,因为可以修改本地 hosts 覆盖掉 DNS 服务的域名解析,相当于绕过了域名检测。
但对于设计来就是用作公共数据接口的,用这种方法解决跨域问题可以省去前端研发人员的时间。
代理
由于在生产环境中可以在 nginx 上把服务端代理到 /api
上,所以我们在开发阶段也可以使用这种代理的思路,在开发环境下使用相关的技术代理到开发环境下的 /api
上即可达到目的。
vue
vue-cli 3.0 使用的是 http-proxy-middleware
这个模块,也可以在之前的版本使用
首先在项目根目录建立 vue.config.js
文件
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://10.1.5.5:8111/mitkimi-web', //对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
这样项目的开发环境就生成了一个代理,调用接口时就可以直接用 /api
代替域名,例如调用 http://10.1.5.5:8111/mitkimi-web/passport/signin
时,即可使用 /api/passport/signin
调用。
我写的 bug 可能要遗臭万年了...