跨域解决方案&部署vue-element-admin遇到的跨域
Sonder
2019-12-20
2538字
6分钟
浏览 (5.2k)
同源策略
同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指”协议+域名+端口”三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
常见的跨域场景
URL | 说明 | 是否允许通信 |
---|---|---|
www.domain.com/a.js www.domain.com/b.js www.domain.com/lab/c.js | 同一域名,不同文件或路径 | 允许 |
www.domain.com:8000/a.js www.domain.com/b.js | 同一域名,不同端口 | 不允许 |
<http://www.domain.com/a.js> <https://www.domain.com/b.js> | 同一域名,不同协议 | 不允许 |
<http://www.domain.com/a.js> <http://192.168.4.12/b.js> | 域名和域名对应相同ip | 不允许 |
<http://www.domain.com/a.js> <http://x.domain.com/b.js> <http://domain.com/c.js> | 主域相同,子域不同 | 不允许 |
<http://www.domain1.com/a.js> <http://www.domain2.com/b.js> | 不同域名 | 不允许 |
部署vue-element-admin
跨域报错:
前端:
- 在
axios.js
中加上运行跨域axios.defaults.withCredentials = true;
- 在
vue.config.js
中检查devServer
devServer: {
port: port,
open: true,
https: false,
proxy: {
"/api": {
target: process.env.VUE_APP_ApiURL, // 需要请求的地址
changeOrigin: true, // 是否跨域
ws: true,
pathRewrite: {
"^/api/": "/" // 替换target中的请求地址
}
}
}
},
至此,前端任务完成
后端(tp5):
- 在 application->tags.php 文件中添加如下代码
// 应用初始化
'app_init' => [
'app\\api\\behavior\\CORS'
],
- 新建文件 application->api->behavior->CORS.php
注意:跨域如果想带cookie(本项目就带有cookie),Access-Control-Allow-Origin
就不能设置为*
,需要指定具体域名。
Access-Control-Allow-Credentials: true
和 Access-Control-Allow-Origin: *
不能同时使用。
<?php
namespace app\api\behavior;
class CORS
{
public function appInit(&$params)
{
$white_list = ['https://a.baidu.fun', 'http://b.baidu.fun'];
if (!empty($_SERVER['HTTP_ORIGIN']) && in_array($_SERVER['HTTP_ORIGIN'], $white_list)) {
$http_origin = $_SERVER['HTTP_ORIGIN'];
//设置 header 信息
header("Access-Control-Allow-Origin: {$http_origin}");
header("Access-Control-Allow-Methods", "POST,GET");
header('Access-Control-Allow-Credentials:true'); //允许访问Cookie
header('Access-Control-Allow-Headers : x-token, Origin, X-Requested-With, Content-Type, Accept'); //设置Headers
if (request()->isOptions()) {
exit();
}
}
}
}
至此,后端任务完成
可能会遇见的问题
两次请求的头居然都不同:
主要是后端问题
为何获取getUserInfo接口请求的是option?
原因(群里的一位大佬解释):浏览器的嗅探;浏览器发现你要跨域了,于是决定给api发个options请求看看后台支持不支持跨域,后台如果返回符合要求的响应头,就可以跨域,否则就报错;需要有个中间件处理option请求,这里就是用CORS.php
来处理的。
报错看图
因为我这里自定义了cookie:x-token
,所以要在Access-Control-Allow-Headers
加上
如果后台处理了跨域,可以忽略。这是在本地的时候才会出现,传上线后就没有了