springboot配置Cors跨域
1、使用@CrossOrigin 注解实现
- 方法上添加 @CrossOrigin 注解 :
@CrossOrigin(origins = {"http://localhost:9000", "null"})
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String greetings() {
return "{\"project\":\"just a test\"}";
}
- 类注解,对该类声明所有接口都有效:
@CrossOrigin(origins = {"http://localhost:9000", "null"})
@RestController
@SpringBootApplication
public class SpringBootCorsTestApplication {
}
2、使用 配置类 方式:
第一种:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1允许任何域名使用
corsConfiguration.addAllowedHeader("*"); // 2允许任何头
corsConfiguration.addAllowedMethod("*"); // 3允许任何方法(post、get等)
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4
return new CorsFilter(source);
}
}
第二种:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.util.pattern.PathPatternParser;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Description:跨域配置
* @author Acmen-z
* @createDate create in 11:36 2019/10/29
*/
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", buildConfig());
return new CorsWebFilter(source);
}
private CorsConfiguration buildConfig(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 允许跨域访问的域名
corsConfiguration.addAllowedOrigin("*");
// 请求头
corsConfiguration.addAllowedHeader("*");
// 请求方法
corsConfiguration.addAllowedMethod(HttpMethod.DELETE);
corsConfiguration.addAllowedMethod(HttpMethod.POST);
corsConfiguration.addAllowedMethod(HttpMethod.GET);
corsConfiguration.addAllowedMethod(HttpMethod.PUT);
// 预检请求的有效期,单位为秒。
//corsConfiguration.setMaxAge(3600L);
// 是否支持安全证书
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}
}
3、使用Filter 过滤器方式 :配置 CORS 规则,并手动指定对哪些接口有效
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 说明:跨域访问处理
*/
@Component
public class CORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setContentType("textml;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");
response.setHeader("Access-Control-Max-Age", "0");
response.setHeader("Access-Control-Allow-Headers","Origin, No-Cache, X-Requested-With" +
", If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,token,h");
// 是否支持cookie跨域
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("XDomainRequestAllowed", "1");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
原理
无论是通过哪种方式配置CROS,其实都构造CorsConfiguration .一个CROS配置用一个CorsConfiguration类来表示,它的定义如下:
public class CorsConfiguration {
private List<String> allowedOrigins;
private List<String> allowedMethods;
private List<String> allowedHeaders;
private List<String> exposedHeaders;
private Boolean allowCredentials;
private Long maxAge;
}
Spring 中对 CORS 规则的校验,都是通过委托给 DefaultCorsProcessor实现的。
DefaultCorsProcessor 处理过程如下:
- 判断依据是 Header中是否包含 Origin。如果包含则说明为 CORS请求,转到 2;否则,说明不是 CORS 请求,不作任何处理。
- 判断 response 的 Header 是否已经包含 Access-Control-Allow-Origin,如果包含,证明已经被处理过了, 转到 3,否则不再处理
- 判断是否同源,如果是则转交给负责该请求的类处理
- 是否配置了 CORS 规则,如果没有配置,且是预检请求,则拒绝该请求,如果没有配置,且不是预检请求,则交给负责该请求的类处理。如果配置了,则对该请求进行校验。
校验就是根据 CorsConfiguration 这个类的配置进行判断:
- 判断 origin 是否合法
- 判断 method 是否合法
- 判断 header是否合法
- 如果全部合法,则在 response header中添加响应的字段,并交给负责该请求的类处理,如果不合法,则拒绝该请求。
与JSONP的比较
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
参考博文:
http://www.ruanyifeng.com/blog/2016/04/cors.html
https://blog.csdn.net/u014344668/article/details/54948546