@HUST-SuWB
2018-04-22T08:17:59.000000Z
字数 2079
阅读 409
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)@Configurationpublic 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");}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic 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);}@Overridepublic void destroy() {}}
一开始在预检请求的时候,我设置的Access-Control-Allow-Headers是星号,可是后边发现貌似不同的浏览器在处理星号的时候策略不同,导致浏览器兼容性不好。最后改成了把相关的header全列出来的方案。