java - 仅在服务器上使用 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
我做错了什么?
解决方案
我发现一旦将 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
推荐阅读
- hadoop - 错误:hbase:meta 表不一致
- python - 如何使用 Google API 从具有坐标的数据集中获取地址?
- php - 如何将关联数组转换为不同的数组?
- python - 内存错误:sklearn Knearest Neighbor knn
- ios - UITableView, cellForRowAt 分配数据的问题
- reactjs - React Native 中的响应式图像
- sql - 如何在 Access 中选择两个日期之间的记录?
- java - 字谜 - 我怎样才能通过以下两个测试用例
- laravel - 如何将cookie从后端(laravel)发送到前端?
- python - 如何在不使用 REGEX 的情况下删除具有特定模式的字符串?