首页 > 解决方案 > 仅在服务器上使用 Spring Boot 2.3 + 安全性没有“Access-Control-Allow-Origin”

问题描述

我正在尝试使用 Spring Boot 2.3 和 Spring Security 与 Angular 前端一起启用 CORS,但出现此错误:

Access to XMLHttpRequest at 'https://api.example.com.br/login' from origin 'https://app.example.com.br' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

一开始 CORS 不能同时在本地运行,所以我尝试了不同的解决方案:

1 - 创建一个 corsConfigurationSource() 像文档:

https://docs.spring.io/spring-security/site/docs/5.3.2.RELEASE/reference/html5/#cors

2 - 现在我这样创建:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowedHeaders("Authorization", "Program", "authorization",
                "Content-Type", "User-Agent", "Origin", "X-XSRF-TOKEN")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS");
    }

}

我的网络安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
@AllArgsConstructor
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private CustomUserDetailsService customUserDetailsService;

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

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests()
                .antMatchers("/", "/favicon.ico", "/**/*.png", "/**/*.gif", "/**/*.svg", "/**/*.jpg", "/**/*.html",
                        "/**/*.css", "/**/*.js")
                .permitAll().antMatchers("/login").permitAll().anyRequest().authenticated();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {

    }
}

现在它在前端和后端在本地主机上运行时工作。

但是当我在服务器上部署后端时,CORS 仍然无法正常工作。

Front and Back at Local = OK
Front Local and Back Server = Not Working
Front Server and Back Server = Not Working

我做错了什么?

标签: javaspring-bootnginxspring-security

解决方案


我发现一旦将 Spring Security 添加到组合中,@CrossOrigin注释就会停止工作。过滤器通常可以为我解决问题。这是用 Kotlin 编写的。

@SpringBootApplication
class DemoApplication {

    @Value("#{ @environment['allowed.origins'] ?: {} }")
    private lateinit var allowedOrigins: List<String>

    @Bean
    fun simpleCorsFilter(): FilterRegistrationBean<CorsFilter> {
        val source = UrlBasedCorsConfigurationSource()
        val config = CorsConfiguration()
        config.allowCredentials = true
        config.allowedOrigins = allowedOrigins
        config.allowedMethods = listOf("*");
        config.allowedHeaders = listOf("*")
        source.registerCorsConfiguration("/**", config)
        val bean = FilterRegistrationBean(CorsFilter(source))
        bean.order = Ordered.HIGHEST_PRECEDENCE
        return bean
    }
}

一位朋友 Micah Silverman 以另一种方式解决了这个问题。

@SpringBootApplication
public class DemoApplication {

    @Value("#{ @environment['allowed.origins'] ?: {} }")
    private List<String> allowedOrigins;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

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

对于第二个示例,您需要http.cors().and()在 Spring Security 配置中。

对于这两者,您可以在以下位置配置允许的来源application.properties

allowed.origins=http://localhost:4200,https://production.url.com

推荐阅读