说明
新版Chrome浏览器导致 cookie 跨域失败,详见:cookie跨域失败-新版chrome浏览器SameSite属性
适用场景
本文只适用 简单请求 携带 cookie,原因详见 链接
非简单请求 携带 cookie,详见 链接
filter代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 处理跨域的过滤器
*/
@WebFilter("/*")
public class CORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");//允许可访问的域列表
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");
response.setHeader("Access-Control-Max-Age", "3600");//设置 Preflight 请求缓存多长时间(以秒为单位)。
//response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");//允许携带cookie。还需要ajax配合,见下面例子
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
解释
Access-Control-Allow-Origin 头
允许可访问的前端服务器列表,* 表示允许任意服务器
注意:末尾不能有符号: /,如下:
response.setHeader("Access-Control-Allow-Origin", "*");
Access-Control-Allow-Headers 头
告诉前端,发请求时,允许携带的请求头,*,表示允许所有请求头
如下:
response.setHeader("Access-Control-Allow-Headers", "*");
Access-Control-Allow-Methods 头
表示允许请求方法,如:POST, GET, OPTIONS, DELETE, HEAD, PUT
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");
Access-Control-Allow-Credentials 头
true 表示允许携带 cookie,还需要ajax配合
response.setHeader("Access-Control-Allow-Credentials", "true");
设置 Preflight 请求缓存时间
非简单请求,先发送 OPTIONS 请求,该请求称为:Preflight 预检请求,然后才发送正式请求
该设置表示:在一段时间内,不再发送Preflight 预检请求,以秒为单位
response.setHeader("Access-Control-Max-Age", "3600");
提示:由于本文适用 简单请求,所以被设置不写也可以
注解配置
在类名上,加下面注解:
@WebFilter("/*")
类名
类名必须是 A0CORSFilter,即:以 A0开头
因为使用 @WebFilter 注解,无法指定过滤器的执行顺序,只会根据 类名 的 ascii码 的顺序,作为 执行顺序,所以为了保证 最先执行该跨域过滤器,类名以 A0开头
web.xml 配置
如果使用 web.xml 配置启用过滤器,加上下面配置:
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>top.malaoshi.filter.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
ajax
jquery
$.ajax({
url:baseUrl+'goods/list',
type:'post',
dataType:'json',//服务器端返回的数据格式是json
xhrFields: { // 默认跨域时不携带cookie,需要指明携带cookie
withCredentials: true
},
data: {
"status":1
},//发给服务器端的数据
success:function(res){ //data:服务器端返回给浏览器端的数据
if(res.code==0){
console.log(res)
}else{
alert(res.msg);
}
},
error:function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest);
alert(textStatus);
alert(errorThrown);
}
});
axios
axios.get(
baseUrl+'goods/list?status=1',
{withCredentials: true}//带cookie
).then(function(res){
console.log(res.data);
})
或者
axios.defaults.withCredentials = true;//带cookie
axios.get(baseUrl+'goods/list?status=1').then(function(res){
console.log(res.data);
})