问题的起因
今天公司的一个小项目需要跑到Android上面,本身是通过token鉴权的,所以移植比较简单。但是在处理 跨域 问题的时候着实给踩了个大坑。
网上说的重写 addCorsMapping
等方法在一般处理上没有大问题. 但是在统一异常拦截器上面有很大的问题.
spring提供的跨域, 只是在响应是Controller
时生效, 而统一异常拦截器ControllerAdvice
是通过AOP处理的. 并且我们在很多时候需要通过自己的拦截器, 过滤器处理内容. 所以spring提供的跨域封装, 并不能很好的解决问题. 最后通过自己编写Filter解决了这个问题. 在此做一个小记录, 以后遇到需要跨域的问题时,直接使用此方法, 比使用spring封装的内容要好很多.
顺便提一下, 关于跨域时 PUT
和DELETE
两个复杂请求的参数处理, 由于这两个请求在发起之前都会发起一个 预请求
, 具体可以看一下 这篇博客, 如果不做处理的话, PUT请求将得不到参数. 具体处理方法也在下面代码区给出.
更新:
是我太年轻, 统一异常拦截器还是没有办法正常的返回, 最后在统一异常拦截器的response上面加上了Origin的设置. 下面展示代码
@CrossOrigin
response.setHeader("Access-Control-Allow-Origin", "*");
代码
@WebFilter
public class CorsFilter extends OncePerRequestFilter {
private static final String ORIGIN = "Origin";
private static final String HEADERS = "Access-Control-Request-Headers";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 获取请求头中的 'Origin' 信息
String origin = request.getHeader(ORIGIN);
// 获取请求头中的 'header' 信息
String headers = request.getHeader(HEADERS);
/**
* 1.支持任何域名跨域访问
* 当 'Access-Control-Allow-Origin' 设置为 '*' 时,不能解决带 Cookie 的跨域
*/
if (!StringUtils.isEmpty(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
}
/**
* 2.支持自定义请求头的跨域
*/
if (!StringUtils.isEmpty(headers)) {
response.setHeader("Access-Control-Allow-Headers", headers);
}
// 3.设置支持带 Cookie 的跨域请求
response.setHeader("Access-Control-Allow-Credentials", "true");
// 4.设置允许跨域请求的方法形式 'GET'、'DELETE' 等
response.setHeader("Access-Control-Allow-Methods", "*");
// 5.设置非简单请求的预检命令缓存时间,单位 's'
response.setHeader("Access-Control-Max-Age", "1728000");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(request, response);
}
}
}
针对PUT请求参数的处理
@Component
public class PutFilter extends HttpPutFormContentFilter {
}