导读


根据项目需求,要添加一个跨域访问判断。

使用


方式一(推荐)

配置CsrFilters过滤器

  1. import org.springframework.beans.factory.annotation.Value;
  2. import org.springframework.core.annotation.Order;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletRequest;
  8. import javax.servlet.ServletResponse;
  9. import javax.servlet.annotation.WebFilter;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.IOException;
  13. import java.util.Arrays;
  14. import java.util.HashSet;
  15. import java.util.Set;
  16. /**
  17. * <p>
  18. * 跨域问题解决,只允许指定的访问
  19. * </p>
  20. */
  21. @Order(Integer.MAX_VALUE - 2) //设置Filter执行顺序,越大越先执行
  22. @WebFilter(urlPatterns = "/*", filterName = "domainFilter") //设置过滤规则,这里过滤所有请求
  23. public class CsrFilters implements Filter {
  24. /**
  25. *设置运行请求源
  26. */
  27. @Value("${allow-origin}")
  28. private String domain;
  29. @Override
  30. public void init(FilterConfig filterConfig) throws ServletException {
  31. }
  32. @Override
  33. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  34. HttpServletResponse response = (HttpServletResponse) res;
  35. //因为允许多个域访问,所以进行分割判断
  36. String[] allowDomain = domain.split(",");
  37. Set<String> allowedOrigins = new HashSet<String>(Arrays.asList(allowDomain));
  38. //从请求头获取Orgin信息
  39. String originHeader = ((HttpServletRequest) req).getHeader("Origin");
  40. if (allowedOrigins.contains(originHeader)) {
  41. response.setHeader("Access-Control-Allow-Origin", originHeader);
  42. response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
  43. response.setHeader("Access-Control-Max-Age", "3600");
  44. response.setHeader("Access-Control-Allow-Headers", "content-type, x-requested-with");
  45. response.setHeader("Access-Control-Allow-Credentials", "true");
  46. }
  47. chain.doFilter(req, res);
  48. }
  49. @Override
  50. public void destroy() {
  51. }
  52. }

配置文件application.yml

  1. #防止跨站请求安全地址
  2. req_filter_urls: http://localhost,http://127.0.0.1

方式二

过滤器CSRFFilter

  1. import java.io.IOException;
  2. import javax.servlet.Filter;
  3. import javax.servlet.FilterChain;
  4. import javax.servlet.FilterConfig;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.ServletRequest;
  7. import javax.servlet.ServletResponse;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. /**
  11. * <p>
  12. * 功能:防止跨站请求伪造过滤器
  13. * </P>
  14. */
  15. public class CSRFFilter implements Filter {
  16. /**
  17. *登录页面放行
  18. */
  19. private static final String HOME_URL = "/login.html";
  20. private FilterConfig filterConfig = null;
  21. @Override
  22. public void destroy() {
  23. this.filterConfig = null;
  24. }
  25. @Override
  26. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  27. throws IOException, ServletException {
  28. HttpServletRequest req = (HttpServletRequest) request;
  29. HttpServletResponse resp = (HttpServletResponse) response;
  30. // 从http头中获取Referer
  31. String referer = req.getHeader("Referer");
  32. // 系统配置的referer头信息
  33. String myReferer = filterConfig.getInitParameter("referer");
  34. //取消拦截登录界面
  35. if (req.getRequestURI().equals(CSRFFilter.HOME_URL)) {
  36. chain.doFilter(request, response);
  37. }
  38. int count = 0;
  39. if (myReferer != null && referer != null) {
  40. if (myReferer.trim().length() > 0) {
  41. String[] myReferers = myReferer.split(",");
  42. for (String s : myReferers) {
  43. if (!referer.trim().startsWith(s)) {
  44. count++;
  45. } else {
  46. chain.doFilter(request, response);
  47. break;
  48. }
  49. }
  50. if (count == myReferers.length) {
  51. System.out.println("检测到您发送的请求可能为跨站伪造请求:" + HttpServletResponse.SC_BAD_REQUEST);
  52. resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
  53. }
  54. }
  55. } else {
  56. System.out.println("检测到您发送的请求可能为跨站伪造请求:" + HttpServletResponse.SC_BAD_REQUEST);
  57. resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
  58. }
  59. }
  60. @Override
  61. public void init(FilterConfig filterConfig) throws ServletException {
  62. this.filterConfig = filterConfig;
  63. }
  64. }

设置过滤FilterConfig

  1. import com.demo.security.filter.CSRFFilter;
  2. import org.springframework.beans.factory.annotation.Value;
  3. import org.springframework.boot.web.servlet.FilterRegistrationBean;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. import javax.servlet.DispatcherType;
  9. /**
  10. * Filter配置
  11. */
  12. @Configuration
  13. public class FilterConfig {
  14. /**
  15. * 设置过滤的地址
  16. */
  17. @Value("#{'${req_filter_urls}'}")
  18. private String domains;
  19. @Bean
  20. public FilterRegistrationBean csrfFilterRegistration() {
  21. FilterRegistrationBean registration = new FilterRegistrationBean();
  22. registration.setDispatcherTypes(DispatcherType.REQUEST);
  23. registration.setFilter(new CSRFFilter());
  24. registration.addUrlPatterns("/*");
  25. registration.setName("csrfFilter");
  26. registration.setEnabled(true);
  27. Map<String, String> initParameters = new HashMap<>();
  28. initParameters.put("referer", domains);
  29. initParameters.put("excludeUrlPattern", "/login.html");
  30. registration.setInitParameters(initParameters);
  31. registration.setOrder(Integer.MAX_VALUE - 2);
  32. return registration;
  33. }
  34. }

**

配置文件application.yml

  1. #防止跨站请求安全地址
  2. req_filter_urls: http://localhost,http://127.0.0.1

检查是否支持跨域

在浏览器上打开一个网站(非https的网站),比如有道词典等,F12后在console里输入:

  1. (function loadXMLDoc() {
  2. var xmlhttp;
  3. xmlhttp = new XMLHttpRequest();
  4. xmlhttp.onreadystatecatechange = function() {
  5. }
  6. xmlhttp.open("GET", "http://localhost/api/getList?beginTime=1990-01-01", true);
  7. xmlhttp.withCredentials = true;
  8. xmlhttp.send();
  9. })()

如下:
image.png

END


参考:链接
搞定~