遇到的问题:
某个老系统使用Vue+Axios+PHP开发,本身是部署在同一域名下
这时候不会涉及到跨域问题
但是奈何线上服务器带宽不够用,且JS、CSS、图片等静态资源加载很缓慢
只能把静态资源迁移到阿里云的OSS存储对象里
导致现在出现了跨域,而且无法携带Cookie,因为是老系统,不太可能改成类似JWT的形式
abc.com指向了OSS的静态地址用于打开前端页面
而JS请求的后台接口地址变成了api.com
这时候后台在header头返回了Set-Cookie也没用
因为同源策略,浏览器拒绝写入Cookie
找了网上很多博客说的是用二级域名的形式去做跨域Cookie
但是我这种完全不相同的域名,以上情况对我来说没有用
先贴出伪静态规则
Apache
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?s=/$1 [QSA,PT,L]
</IfModule>
Nginx
if (!-d $request_filename){
set $rule_0 1$rule_0;
}
if (!-f $request_filename){
set $rule_0 2$rule_0;
}
if ($rule_0 = "21"){
rewrite ^/(.*)$ /index.php?s=/$1 last;
}
PHP入口函数的地方添加上header(如果支持中间件的框架,可以把该代码略微修改放在中间件里面)
这里值得注意的是
在80内核的Chrome浏览器Access-Control-Allow-Origin必须要指定一个具体的地址,即 http://a.com:8080 这种协议+域名+端口的形式,不能使用*号
header('Access-Control-Allow-Origin:'.$_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods:GET,POST,PUT,DELETE,OPTIONS,*');
header('Access-Control-Allow-Headers:DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Accept-Language, Origin, Accept-Encoding,Cookie');
header('Access-Control-Allow-Credentials:true');
if(strtoupper($_SERVER['REQUEST_METHOD'])=='OPTIONS'){
http_response_code(204);exit;
}
前端Axios要设置允许携带Cookie(如果使用JWT令牌的话,可以不用这个)
axios.defaults.withCredentials = true;
此时在火狐浏览器已经能够成功的进行跨域携带Cookie打开系统了
但查了资料,Chrome浏览器内核大于80之后做了调整,需要显式的设置SameSite设置为None
但是我这里试了一下,还是不行,不知道是哪里姿势不对
最终我把abc.com加了个SSL、请求的api.com也加了SSL
在用Chrome浏览器打开(先清缓存,访问要带https)
到这就可以实现前后端分离部署+跨域+Cookie访问接口了
总结一下:
后端要允许跨域,设置header头的时候orgin不能设置为*号
如果能够修改Apache或者Nginx的配置文件也是可以实现跨域的
前端也要设置允许跨域携带Cookie
最后前端和后端的地址都加上SSL,用HTTPS进行访问
以上跨域携带Cookie经过Chrome(版本90)、Firefox、Edge、360极速浏览器测试