前言:公司的SpringBoot项目出于某种原因,经常样处理一些跨域请求。
一。以前通过查阅相关资料自己写的一个处理跨域的类,如下。
1.1首先定义一个filter(拦截所有请求,包括跨域请求)
public class CrossDomainFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest hreq = (HttpServletRequest) request; //
HttpServletResponse hresp = (HttpServletResponse) response;
//跨域
hresp.setHeader("Access-Control-Allow-Origin", "*"); //设置相应头
//跨域 Header
hresp.setHeader("Access-Control-Allow-Methods", "*");
hresp.setHeader("Access-Control-Allow-Headers", "Content-Type,XFILENAME,XFILECATEGORY,XFILESIZE,x-requested-with,requesttype");
//header('Access-Control-Allow-Headers:x-requested-with,content-type,requesttype');
// 浏览器是会先发一次options请求,如果请求通过,则继续发送正式的post请求
// 配置options的请求返回
if (hreq.getMethod().equals("OPTIONS")) { //如果发现该请求为OPTION,则直接返回(不需要进入系统),并且设置相应信息
hresp.setStatus(200);
// hresp.setContentLength(0);
hresp.getWriter().write("OPTIONS returns OK");
return;
}
// Filter 只是链式处理,请求依然转发到目的地址。
chain.doFilter(request, response);
}
}
1.2 注册一个配置类(Configuration),把上面定义的filter类注册到上下文环境中
@Configuration
public class WebConfiguration {
@Bean
public RemoteIpFilter remoteIpFilter() {
return new RemoteIpFilter();
}
@Bean
public FilterRegistrationBean<CrossDomainFilter> testFilterRegistration() {
FilterRegistrationBean<CrossDomainFilter> registration = new FilterRegistrationBean<CrossDomainFilter>();
registration.setFilter(new CrossDomainFilter());
registration.addUrlPatterns("/*");
registration.addInitParameter("paramName", "paramValue");
registration.setName("MyFilter");
registration.setOrder(1);
return registration;
}
}
备注:这个配置类主要解决我们编写的filter(CrossDomainFilter )拦截那些请求
二. SpringBoot自己的解决跨域的Filter(CorsFilter) ,该filter的源码很简单,可直接查看还类的doFilterInternal() 方法,因为该发法在doFilter()方法中会调用(可以理解就是Filter的doFilter()方法)。
处理过程也是接受到OPTION方法并相应200并返回。
@Configuration
@EnableAutoConfiguration
public class CrossOriginconfig {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
// 设置你要允许的网站域名,如果全允许则设为 *
corsConfiguration.addAllowedOrigin("*");
// 如果要限制 HEADER 或 METHOD 请自行更改
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
System.out.println("confi init");
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
三:个人对跨域问题的小结
浏览器在发送请求之前,最先检测到跨域问题,并在发送跨域请求之前先发送了一个类型为OPTIONS的请求(请求地址不变,并且请求头上携带了一些其他信息),该请求必须得到服务器响应(请查CrossDomainFilter ),如果该请求没有得到响应,则浏览器不会发送真正的请求了。
3.1 :浏览器发送的OPTION请求(试探性的请求)
备注: 有图我们发现请求地址不变(),请求方法为OPTION,并且请求头中携带了一些信息该信息可以表明我是一个跨域请求,并且请求的方式是POST。。
3.2 :服务器需要对该请求做出相应,(请查CrossDomainFilter )
1)首先设置相应相应头(告诉浏览器我支持的跨域请求的一些信息)
2) 设置相应状态为200,并且返回数据(任意数据)
3.3 :浏览器获得到了OPTION请求的相应(服务器接受跨域),故放心发送真正的请求,如下
1)对比OPTION请求,请求地址没变^_^
2)对比请求方式该请求为POST. 并且POST请求在OPTIN中已经告诉服务器了(Access-Control-Request-Method)。
3)对比OPTION请求的头,该请求并没有Access-Control-Allow-****的相关参数。
,