在过滤器里面添加头就可以了,但是会碰到下面的问题:
. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
当前端请求有参数:
withCredentials: true的时候会出现上述问题,因为浏览器的安全策略,当允许 credentials 的时候,Access-Control-Allow-Origin 值不能是*
,而必须是一个指定的域名, 那么如何针对不同的访问设定对应的跨源允许域呢?
HTTP 中的Referer能很好地实现该需求,当在一个域下发起一个 CORS 请求时,HTTP 请求头的 Referer 值会自动被设置为当前页面域,此时只要在服务器端读取 Referer 值,构造出相应的 Access-Control-Allow-Origin 值即可,参考下面代码
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String referer = req.getHeader("referer");
HttpServletResponse res = (HttpServletResponse) response;
if (!StringUtils.isEmpty(referer)) {
try {
res.setHeader("Access-Control-Allow-Origin", getHost(referer));
} catch (Exception e) {
log.error(e.getMessage(), e);
res.setHeader("Access-Control-Allow-Origin", "*");
}
} else {
res.setHeader("Access-Control-Allow-Origin", "*");
}
res.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, token, nonce, signature, uid");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 防止流读取一次后就没有了, 所以需要将流继续写出去
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);
chain.doFilter(requestWrapper, response);
}
private String getHost(String referer) {
String split = "/";
String[] ss = referer.split(split);
return ss[0] + split + ss[1] + split + ss[2];
}