文章目录
- 问题描述
- 开发环境
- 解决方案
- 前端部分
- 后端部分
- 部分解决问题
- 全局支持跨域
- 效果图
- 部分问题
- 被识别为跨站攻击
- 解决方案
- 普罗大众式
- 突发奇想式
- 绝对离谱式
- 相对靠谱(推荐)
- 最终选取方案
问题描述
请求地址不同所引发的报错问题
提示信息:blocked by CORS policy: No ‘Access-Control-Allow-Origin‘ header is present on the requested resource
开发环境
前端:Vue + html三件套 + Axios(用于发送异步请求)
后端:javax.servlet
+ Mybatis
解决方案
前端部分
在axios请求中添加withCredentials: true
使得axios允许携带cookie
例子:
axios({
method:'post',
url:"http://127.0.0.1/user/login",
data:{"email": "2776483968@qq.com","password": "*"},
withCredentials: true // 允许携带cookie
}).then(resp=>{
console.log(resp);
})
axios({
method:'get',
url:"http://127.0.0.1/user",
withCredentials:true // 允许携带cookie
}).then(resp=>{
console.log(resp);
})
后端部分
有两种解决方式,一种是部分解决跨域问题,另一种是全局支持跨域问题
个人感觉如果全局支持会导致网站的安全性下降,谨慎使用
部分解决问题
在服务端添加响应头:response.setHeader("Access-Control-Allow-Origin","*");
第二个参数是 * 表示允许任何域名跨域访问
response.setHeader("Access-Control-Allow-Origin","http:localhost:8080");
第二个参数是特定域名则只有它可以访问
全局支持跨域
写一个Filter
过滤器过滤地址\*
就可以全局过滤了
具体代码如下
package cn.imerji.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "Filter_CrossOrigin",urlPatterns = "/*")
public class Filter_CrossOrigin implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request1 = (HttpServletRequest) request;
HttpServletResponse response1 = (HttpServletResponse) response;
response1.setHeader("Access-Control-Allow-Origin", request1.getHeader("origin"));
response1.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response1.setHeader("Access-Control-Max-Age", "3600");
response1.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
response1.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request1, response1);
}
}
效果图
但是如果域名不同会引发下述问题
部分问题
被识别为跨站攻击
通过谷歌浏览器的报错SameSite
属性了解到,可能发送请求cookie时被认为是跨站攻击
Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。
最好的办法,不要搞这样的开发
。
解决方案
普罗大众式
首先要将SameSite
属性设置为None
,其次要使用https
安全链接。
突发奇想式
两个网站使用同一个一级域名,
比如a网站域名为: a.xxxx.com
b网站域名为: b.xxxx.com
绝对离谱式
使用Chrome(谷歌)浏览器打开chrome://flags/#site-isolation-trial-opt-out
把SameSite by default cookies
设置为disabled
,重启浏览器即可正常使用
但是好像不是每个人都可以设置自己的浏览器,所以绝对离谱
虽然离谱但是有效
事件起因
相对靠谱(推荐)
直接把session按照SameSite的需求重写一遍set
response.addHeader("Set-Cookie", String.format("%s; %s", String.format("JSESSIONID=%s; Max-Age=%s; Path=/;%s HttpOnly", request1.getSession().getId(), 3600, " Secure;"), "SameSite=None"));
我选择的是用过滤器每一次请求都设置一次Session,如果正式开发我肯定不会这么考虑(但是问题解决了
)
最终选取方案
前端设置好withCredentials
后端采用了普罗大众式
写好过滤器Filter
,并且重新写好set-Cookie
的格式