您的位置:

WebMvcConfigurer的跨域配置

一、什么是跨域?

跨域(Cross-origin)是指在浏览器端,一个页面从一个域名跳转到另一个域名的过程。在这个过程中,如果跳转的页面访问了另一个域名下的资源,比如Ajax访问API、通过iframe加载资源等,就会涉及到跨域问题。跨域问题是一个很普遍的网络安全问题,浏览器提供了一些机制限制页面的跨域访问,包括限制Cookie、dom访问、数据读取等。

二、为什么需要跨域配置?

在开发中,通常会存在多个应用系统,有时候需要在这些系统之间进行数据的共享和交换,这时候就会出现跨域问题。跨域的目的是为了限制JavaScript对不同源(domain)的访问,进而保障了网络安全。但是在某些场景下,如果跨域没有设置,将会无法正常调用API或者无法获取到相关资源,导致应用程序无法正常工作。

三、在Spring Boot中配置跨域

Spring Boot通过WebMvcConfigurer类提供了一个非常方便的方式来解决跨域问题。要开启跨域支持,首先需要创建一个WebMvcConfigurer类,并实现addCorsMappings方法。该方法将会配置跨域请求处理的细节,包括允许哪些域名、方法、响应头等。

@Configuration
public class CorsConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .maxAge(3600)
                .allowedHeaders("*")
                .allowCredentials(true);
    }
}

代码解释:

  1. addMapping:允许跨域访问的路径
  2. allowedOrigins:允许跨域访问的域名,设置成“*”表示允许所有来源
  3. allowedMethods:允许跨域访问的请求方法
  4. maxAge:缓存时间,在该时间内只需再次发起预检请求
  5. allowedHeaders:允许跨域访问的请求头
  6. allowCredentials:是否允许发送Cookie,默认为false

四、Spring Boot跨域配置中的注意点

在进行跨域配置的时候,需要注意以下几点:

1. 支持OPTIONS请求

在进行跨域请求时,会先发一个OPTIONS请求,通过该请求获取服务器的响应,然后才会发送真正的请求。因此必须在跨域配置中加入OPTIONS请求。

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
            .allowedOrigins("*")
            .allowedMethods("*")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
}

2. 支持带Cookie的请求

默认情况下,跨域是不支持带Cookie的请求的,可以通过以下配置开启Cookie支持。

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
            .allowedOrigins("*")
            .allowedMethods("*")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
}

需要注意的是,允许带Cookie时会增加安全风险,只应在必要时开启。

3. 配置粒度优化

如果想对某个具体的Controller进行跨域配置,可以直接在该Controller中配置。例如下面的代码只对UserController进行跨域配置,而不是全局配置:

@RestController
@RequestMapping("/users")
public class UserController {

    @CrossOrigin(origins = "*", maxAge = 3600)
    @GetMapping
    public List getAllUsers() {
        return userService.getAllUsers();
    }

}

  

需要注意的是,使用@CrossOrigin注解需要搭配配置类中的.addMapping("/users")或全部路径.addMapping("/**"),否则@CrossOrigin注解将不会生效。

五、使用Spring Security配置跨域

在使用Spring Security时,可能会因为跨域而无法进行正常访问,需要进行相应的配置,与跨域配置一样,同样需要重写WebSecurityConfigurerAdapter中的configure方法。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/api/**").permitAll()
            .anyRequest().authenticated()
            .and().cors().configurationSource(corsConfigurationSource())
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/api/**", configuration);
        return source;
    }
}

代码解释:

  1. anyRequest().authenticated():要求所有请求都要经过认证
  2. cors():开启跨域
  3. configurationSource():属性配置

六、总结

在跨域请求的过程中,可以通过配置WebMvcConfigurer或Spring Security来解决跨域问题。正确地配置跨域可以使得应用程序顺畅地工作,增强了跨系统之间的数据共享与交换。