@HUST-SuWB
2018-04-22T08:17:59.000000Z
字数 2079
阅读 319
Finlabtech
来这边以后已经开发了两个系统了,结果每个系统正式上线之前都会碰到蛋疼的跨域问题。百度CORS跨域的话,排第一的就是阮一峰老师的博客跨域资源共享 CORS 详解,这篇文章其实介绍得相当详细了,怎奈一开始没看懂,最后还是折腾了半天。这次下定决心把问题记录清楚,省得后边再反复的纠结这个事情。
在目前前后端分离的主流背景下,可以说跨域必不可免。而CORS就是一个支持浏览器跨域访问的标准。为了实现CORS,服务端需要做相应的配置。
简单的说,对于非简单请求,浏览器会先发送一个OPTION的请求进行预检,可以理解为确定服务器是否接受客户端的请求,接受才会发起真正的请求,那么重点就是在预检请求的时候,服务端需要返回给浏览器一些标识,比如Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers等。
一种简单的实现方式是增加一个过滤器Filter,对于所有的预检请求做处理。
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* 支持跨域
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
public class CrosFilter implements Filter {
private static final Set<String> DISALLOWED_METHOD = new HashSet<>();
static {
DISALLOWED_METHOD.add("OPTIONS");
DISALLOWED_METHOD.add("PUT");
DISALLOWED_METHOD.add("DELETE");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET");
response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, x-auth-token, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, Authorization");
response.setHeader("Access-Control-Max-Age", "3600");
if (DISALLOWED_METHOD.contains(request.getMethod())) {
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
一开始在预检请求的时候,我设置的Access-Control-Allow-Headers是星号,可是后边发现貌似不同的浏览器在处理星号的时候策略不同,导致浏览器兼容性不好。最后改成了把相关的header全列出来的方案。