[关闭]
@HUST-SuWB 2018-04-22T08:17:59.000000Z 字数 2079 阅读 319

记一次跨域的解决方案

Finlabtech


起因

来这边以后已经开发了两个系统了,结果每个系统正式上线之前都会碰到蛋疼的跨域问题。百度CORS跨域的话,排第一的就是阮一峰老师的博客跨域资源共享 CORS 详解,这篇文章其实介绍得相当详细了,怎奈一开始没看懂,最后还是折腾了半天。这次下定决心把问题记录清楚,省得后边再反复的纠结这个事情。

简述

在目前前后端分离的主流背景下,可以说跨域必不可免。而CORS就是一个支持浏览器跨域访问的标准。为了实现CORS,服务端需要做相应的配置。
简单的说,对于非简单请求,浏览器会先发送一个OPTION的请求进行预检,可以理解为确定服务器是否接受客户端的请求,接受才会发起真正的请求,那么重点就是在预检请求的时候,服务端需要返回给浏览器一些标识,比如Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers等。

实现

一种简单的实现方式是增加一个过滤器Filter,对于所有的预检请求做处理。

  1. import org.springframework.context.annotation.Configuration;
  2. import org.springframework.core.Ordered;
  3. import org.springframework.core.annotation.Order;
  4. import org.springframework.stereotype.Component;
  5. import javax.servlet.*;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. import java.util.HashSet;
  10. import java.util.Set;
  11. /**
  12. * 支持跨域
  13. */
  14. @Component
  15. @Order(Ordered.HIGHEST_PRECEDENCE)
  16. @Configuration
  17. public class CrosFilter implements Filter {
  18. private static final Set<String> DISALLOWED_METHOD = new HashSet<>();
  19. static {
  20. DISALLOWED_METHOD.add("OPTIONS");
  21. DISALLOWED_METHOD.add("PUT");
  22. DISALLOWED_METHOD.add("DELETE");
  23. }
  24. @Override
  25. public void init(FilterConfig filterConfig) throws ServletException {
  26. }
  27. @Override
  28. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
  29. throws IOException, ServletException {
  30. HttpServletResponse response = (HttpServletResponse) servletResponse;
  31. HttpServletRequest request = (HttpServletRequest) servletRequest;
  32. response.setHeader("Access-Control-Allow-Origin", "*");
  33. response.setHeader("Access-Control-Allow-Methods", "POST, GET");
  34. 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");
  35. response.setHeader("Access-Control-Max-Age", "3600");
  36. if (DISALLOWED_METHOD.contains(request.getMethod())) {
  37. return;
  38. }
  39. filterChain.doFilter(servletRequest, servletResponse);
  40. }
  41. @Override
  42. public void destroy() {
  43. }
  44. }

其他

一开始在预检请求的时候,我设置的Access-Control-Allow-Headers是星号,可是后边发现貌似不同的浏览器在处理星号的时候策略不同,导致浏览器兼容性不好。最后改成了把相关的header全列出来的方案。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注