Spring Boot Security跨域访问 cors

使用Spring Security 在Boot 项目中,实现前后端分离的跨域访问,只需要简单的配置即可。

未使用Security 的Boot 项目

在未使用Spring Security 的Boot 项目中,只需要在 Application.java 中添加如下代码即可

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("PUT", "DELETE", "GET", "POST", "OPTIONS")
                    .allowedHeaders("*")
                    .exposedHeaders("access-control-allow-headers",
                            "access-control-allow-methods",
                            "access-control-allow-origin",
                            "access-control-max-age",
                            "X-Frame-Options")
                    .allowCredentials(true).maxAge(3600);
        }
    };

}

或者单独以Config 的形式

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

	@Override
  public void addCorsMappings(CorsRegistry registry) {
      registry.addMapping("/**")
              .allowedOrigins("*")
              .allowedMethods("PUT", "DELETE", "GET", "POST", "OPTIONS")
              .allowedHeaders("*")
              .exposedHeaders("access-control-allow-headers",
                      "access-control-allow-methods",
                      "access-control-allow-origin",
                      "access-control-max-age",
                      "X-Frame-Options")
              .allowCredentials(true).maxAge(3600);
  }
}

使用Security 的情况

使用Security 时,为了让所有接口都支持跨域,以及支持自定义的 请求方式 (GET POST PUT 等)。只需要增加如下配置:

/**
 * Security 配置
 *
 * @author xuefeihu
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(loginAuthenticationProvider);
        auth.authenticationProvider(tokenAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            // 开启跨域
            .cors().and()

            .exceptionHandling()
            .authenticationEntryPoint(this.authenticationEntryPoint)
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers('/api/login').permitAll()
            .and()
            .addFilterBefore(buildTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
    }

}

使用Security开启允许iframe嵌套

使用上面的配置,当前端页面发生嵌套时,会响应如下响应头,从而不可以嵌套页面。


此时只需要禁用 X-Frame-Options 头即可,如下所示:

/**
 * Security 配置
 *
 * @author xuefeihu
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 开启允许iframe 嵌套
        http.headers().frameOptions().disable();

        http.csrf().disable()
            // 开启跨域
            .cors().and()

            .exceptionHandling()
            .authenticationEntryPoint(this.authenticationEntryPoint)
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers('/api/login').permitAll()
            .and()
            .addFilterBefore(buildTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
    }

}