Spring Boot安全性CORS

use*_*987 14 spring spring-mvc spring-security cors spring-boot

我对弹簧安全URL的CORS过滤器有问题.它没有设置Access-Control-Allow-Origin和属于spring sec(登录/注销)或由Spring Security过滤的URL上的其他公开标头.

这是配置.

CORS:

@Configuration
@EnableWebMvc
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
********some irrelevant configs************
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/*").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT")
                .allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
                        "Access-Control-Request-Headers")
                .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
                .allowCredentials(true).maxAge(3600);
    }
}
Run Code Online (Sandbox Code Playgroud)

安全:

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
                .formLogin()
                    .successHandler(ajaxSuccessHandler)
                    .failureHandler(ajaxFailureHandler)
                    .loginProcessingUrl("/authentication")
                    .passwordParameter("password")
                    .usernameParameter("username")
                .and()
                .logout()
                    .deleteCookies("JSESSIONID")
                    .invalidateHttpSession(true)
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/")
                .and()
                .csrf().disable()
                .anonymous().disable()
                .authorizeRequests()
                .antMatchers("/authentication").permitAll()
                .antMatchers("/oauth/token").permitAll()
                .antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')")
                .antMatchers("/user/*").access("hasRole('ROLE_USER')");
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我向未被安全性监听的url发出请求,则会设置CORS标头.Spring安全URL - 未设置.

Spring boot 1.4.1

mik*_*ika 28

您可以编写自己的CorsFilter,并将其添加到安全配置中,而不是使用CorsRegistry.

自定义CorsFilter类:

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 {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request= (HttpServletRequest) servletRequest;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", true);
        response.setHeader("Access-Control-Max-Age", 180);
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}
Run Code Online (Sandbox Code Playgroud)

安全配置类:

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    CorsFilter corsFilter() {
        CorsFilter filter = new CorsFilter();
        return filter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
                .formLogin()
                    .successHandler(ajaxSuccessHandler)
                    .failureHandler(ajaxFailureHandler)
                    .loginProcessingUrl("/authentication")
                    .passwordParameter("password")
                    .usernameParameter("username")
                .and()
                .logout()
                    .deleteCookies("JSESSIONID")
                    .invalidateHttpSession(true)
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/")
                .and()
                .csrf().disable()
                .anonymous().disable()
                .authorizeRequests()
                .antMatchers("/authentication").permitAll()
                .antMatchers("/oauth/token").permitAll()
                .antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')")
                .antMatchers("/user/*").access("hasRole('ROLE_USER')");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这将不起作用,因为当凭证模式为“包含”时,您不能使用通配符“\*”。我找到的解决方案是在设置“Access-Control-Allow-Origin”标头时用“\*”替换 request.getHeader(“Origin”) 。这对我有用。 (2认同)
  • 对于任何像我一样偶然路过并有点迷失的人来说,我实现的“Filter”是“javax.servlet.Filter”。工作起来就像一个魅力。可能看起来很明显,但希望这可以节省我花在谷歌搜索上的时间。 (2认同)

The*_*ger 28

选项1(使用WebMvcConfigurer bean):

您开始使用的CORS配置不是使用Spring Boot执行此操作的正确方法.你需要注册一个WebMvcConfigurerbean.参考这里.

示例Spring Boot CORS配置:

@Configuration
@Profile("dev")
public class DevConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:4200");
            }
        };
    }

}
Run Code Online (Sandbox Code Playgroud)

这将为基本(无安全启动器)Spring Boot应用程序提供CORS配置.请注意,CORS支持独立于Spring Security.

一旦引入Spring Security,您需要在安全配置中注册CORS.Spring Security足够聪明,可以获取现有的CORS配置.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors().and()              
         ....
Run Code Online (Sandbox Code Playgroud)

选项2(使用CorsConfigurationSource bean):

我描述的第一个选项实际上是从将Spring Security添加到现有应用程序的角度出发的.如果要从一开始就添加Spring Security,Spring Security Docs中概述的方式涉及添加CorsConfigurationSource bean.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 似乎 bean 名称必须是“corsConfigurationSource”,否则不会被拾取? (2认同)

Ike*_*Eze 17

这很干净,不需要任何额外的配置。在您希望所有选项都有效的地方传递星号(就像我在 setAllowedHeaders 中所做的那样)。

@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.cors().configurationSource(request -> {
      var cors = new CorsConfiguration();
      cors.setAllowedOrigins(List.of("http://localhost:4200", "http://127.0.0.1:80", "http://example.com"));
      cors.setAllowedMethods(List.of("GET","POST", "PUT", "DELETE", "OPTIONS"));
      cors.setAllowedHeaders(List.of("*"));
      return cors;
    }).and()...
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是截至 2020 年 12 月已接受的答案(使用 Spring Boot 2.3/2.4) (4认同)
  • 太感谢了。终于解决了我的问题。卡住了大约 3 周,但没有其他解决方案有效! (2认同)