SpringBoot跨域处理
@CrossOrigin(局部跨域)
- @RestController
- public class IndexController {
- @CrossOrigin(value = "http://localhost:8082")
- @GetMapping("/hello")
- public String hello() {
- return "get hello";
- }
- @CrossOrigin(value = "http://localhost:8082")
- @PostMapping("/hello")
- public String hello2() {
- return "post hello";
- }
- }
复制代码- @CrossOrigin(origins = "http://example.com", maxAge = 3600)
- @RestController
- @RequestMapping("/account")
- public class AccountController {
- @RequestMapping(method = RequestMethod.GET, path = "/{id}")
- public Account retrieve(@PathVariable Long id) {
- // ...
- }
- @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
- public void remove(@PathVariable Long id) {
- // ...
- }
- }
复制代码 WebMvcConfigurer(全局跨域)
- @Configuration
- public class WebMvcConfig implements WebMvcConfigurer {
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**")
- .allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
- .allowedMethods("*")
- .allowedOrigins("*")
- .allowCredentials(true);
- }
- }
复制代码 SpringSecurity跨域处理
跨域配置详解
如果利用了 Spring Security,上面的跨域配置会失效,因为请求被 Spring Security 拦截了
在项目中利用 Spring Security,我们必须采取额外的步骤确保它与 CORS 协作精良。这是因为 CORS 需要首先处理,否则,Spring Security 会在请求到达 Spring MVC 之前将其拒绝- @Configuration
- public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.cors().and()...
- }
- }
复制代码 可以配置 CORS 以覆盖默认的 Spring Security CORS 处理器。为此,我们需要添加一个 CorsConfigurationSource Bean,利用 CorsConfiguration 实例来处理 CORS 配置。如果添加了 CorsFilter Bean,http.cors() 方法就会利用 CorsFilter,否则就会利用 CorsConfigurationSource。如果两者都未配置,则利用 Spring MVC pattern inspector handler。- public class CorsConfigurer<H extends HttpSecurityBuilder<H>>
- extends AbstractHttpConfigurer<CorsConfigurer<H>, H> {
- private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
- private static final String CORS_CONFIGURATION_SOURCE_BEAN_NAME = "corsConfigurationSource";
- private static final String CORS_FILTER_BEAN_NAME = "corsFilter";
- private CorsConfigurationSource configurationSource;
- public CorsConfigurer() {
- }
- public CorsConfigurer<H> configurationSource(
- CorsConfigurationSource configurationSource) {
- this.configurationSource = configurationSource;
- return this;
- }
- @Override
- public void configure(H http) {
- ApplicationContext context = http.getSharedObject(ApplicationContext.class);
- CorsFilter corsFilter = getCorsFilter(context);
- if (corsFilter == null) {
- throw new IllegalStateException(
- "Please configure either a " + CORS_FILTER_BEAN_NAME + " bean or a "
- + CORS_CONFIGURATION_SOURCE_BEAN_NAME + "bean.");
- }
- http.addFilter(corsFilter);
- }
- private CorsFilter getCorsFilter(ApplicationContext context) {
- if (this.configurationSource != null) {
- return new CorsFilter(this.configurationSource);
- }
- // 查找是否有名为corsFilter的Bean对象
- boolean containsCorsFilter = context
- .containsBeanDefinition(CORS_FILTER_BEAN_NAME);
- if (containsCorsFilter) {
- return context.getBean(CORS_FILTER_BEAN_NAME, CorsFilter.class);
- }
- // 查找是否有名为corsConfigurationSource的Bean对象
- boolean containsCorsSource = context
- .containsBean(CORS_CONFIGURATION_SOURCE_BEAN_NAME);
- if (containsCorsSource) {
- CorsConfigurationSource configurationSource = context.getBean(
- CORS_CONFIGURATION_SOURCE_BEAN_NAME, CorsConfigurationSource.class);
- return new CorsFilter(configurationSource);
- }
- // 查找是否有org.springframework.web.servlet.handler.HandlerMappingIntrospector该类
- boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
- context.getClassLoader());
- if (mvcPresent) {
- return MvcCorsFilter.getMvcCorsFilter(context);
- }
- return null;
- }
- static class MvcCorsFilter {
- private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
- private static CorsFilter getMvcCorsFilter(ApplicationContext context) {
- if (!context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
- throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, "A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME +" of type " + HandlerMappingIntrospector.class.getName()
- + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
- }
- // 获取名为mvcHandlerMappingIntrospector的Bean对象
- HandlerMappingIntrospector mappingIntrospector = context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class);
- return new CorsFilter(mappingIntrospector);
- }
- }
- }
复制代码 CorsConfigurationSource(全局跨域)
- @Configuration
- public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.authorizeRequests()
- .anyRequest()
- .permitAll()
- .and()
- .formLogin()
- .permitAll()
- .and()
- .httpBasic()
- .and()
- // 支持跨域访问
- .cors()
- // 可以选择配置
- //.configurationSource(corsConfigurationSource())
- .and()
- .csrf()
- .disable();
- }
-
- @Bean
- public CorsConfigurationSource corsConfigurationSource() {
- CorsConfiguration configuration = new CorsConfiguration();
- configuration.setAllowedOrigins(Arrays.asList("*"));
- configuration.setAllowedMethods(Arrays.asList("*"));
- configuration.setAllowedHeaders(Arrays.asList("*"));
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", configuration);
- return source;
- }
- }
复制代码 CosFilter(全局跨域)
还有一种情况就是支持 OAuth2 相关接口的跨域,比如用户要访问 OAuth2 中的 /oauth/token 等接口,可以配置一个全局的 CorsFilter 跨域过滤器类- @Configuration
- public class GlobalCorsConfig {
-
- @Bean
- public CorsFilter corsFilter() {
- //1.添加CORS配置信息
- CorsConfiguration config = new CorsConfiguration();
- //放行哪些原始域
- config.addAllowedOrigin("*");
- //是否发送Cookie信息
- config.setAllowCredentials(true);
- //放行哪些原始域(请求方式)
- config.addAllowedMethod("*");
- //放行哪些原始域(头部信息)
- config.addAllowedHeader("*");
- //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
- config.addExposedHeader("*");
-
- //2.添加映射路径
- UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
- configSource.registerCorsConfiguration("/**", config);
-
- //3.返回新的CorsFilter.
- return new CorsFilter(configSource);
- }
- }
复制代码 自定义Filter(全局跨域)
- public class CorsFilter extends OncePerRequestFilter {
-
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
- String orignalHeader = StringUtils.defaultIfBlank(request.getHeader("Origin"), "*");
- // 指定本次预检请求的有效期
- response.setHeader("Access-Control-Max-Age", "3600");
- // 服务器支持的所有头信息字段
- response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
- response.setHeader("Access-Control-Allow-Origin", orignalHeader);
- response.setHeader("Access-Control-Allow-Credentials", "true");
- response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
- filterChain.doFilter(request, response);
- }
- }
复制代码- @Configuration
- public class WebMvcConfig extends WebSecurityConfigurerAdapter {
-
- @Override
- public void configure(HttpSecurity http) throws Exception {
- http.addFilterBefore(new CorsFilter(), WebAsyncManagerIntegrationFilter.class);
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |