下面是配置。。。
我的后端是localhost:8080,前端是localhost:3000。后端的身份验证仅通过OAuth2处理。基本上,前端用户单击“使用Spotify登录”,会被重定向到处理OAuth2的后端,然后重定向回前端。所有后续请求都来自前端到后端。(前端位于Next.JS BTW中)
这是我的问题。。。
如果我没有经过身份验证,任何对我后端的请求都会抛出一个CORS错误。(如果我通过了身份验证,它将按预期工作)。因此,GET/users/{id},在未登录时,返回CORS,而不仅仅是一个普通的401。这没关系,因为我可以解决它,但是现在由于CORS,我无法向endpoint发出PUT请求,即使在登录时也是如此。。。我尝试了@CrossOrigin注释,但这没有帮助。我也试过了。cors()。在SecurityConfig中禁用(),但是我仍然会在前端引发CORS错误。。。
以下是我用于安全/WebFlux的内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
<version>5.4.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.4.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
这是我的CorsConfig:
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter("/*")
class CorsConfig: WebFluxConfigurer {
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")
.allowCredentials(true)
super.addCorsMappings(registry)
}
}
这是我的安全配置:
@EnableWebFluxSecurity
class SecurityConfig(
@Qualifier("globalErrorHandler")
private val exceptionHandler: WebExceptionHandler,
private val authenticationFailureHandler: ServerAuthenticationFailureHandler,
private val authenticationSuccessHandler: AuthenticationSuccessHandler,
private val authorizationRequestResolver: ServerOAuth2AuthorizationRequestResolver,
private val logoutSuccessHandler: LogoutSuccessHandler
) {
@Bean
fun securityFilterChain(
httpSecurity: ServerHttpSecurity
): SecurityWebFilterChain = httpSecurity
.authorizeExchange()
.pathMatchers("/login", "/register", "/logout").permitAll()
.anyExchange().authenticated()
.and()
.cors().disable()
.exceptionHandling(::withConfiguration)
.oauth2Login(::withConfiguration)
.logout(::withConfiguration)
.csrf().disable()
.build()
fun withConfiguration(spec: ServerHttpSecurity.ExceptionHandlingSpec): Unit =
spec.accessDeniedHandler(exceptionHandler::handle)
.authenticationEntryPoint(exceptionHandler::handle)
.run {}
fun withConfiguration(spec: ServerHttpSecurity.OAuth2LoginSpec): Unit =
spec.authenticationFailureHandler(authenticationFailureHandler)
.authenticationSuccessHandler(authenticationSuccessHandler)
.authorizationRequestResolver(authorizationRequestResolver)
.run { }
fun withConfiguration(spec: ServerHttpSecurity.LogoutSpec): Unit =
spec.logoutUrl("/logout")
.logoutSuccessHandler(logoutSuccessHandler)
.run { }
}
如果您需要更多信息,请随时询问。
这是我的解决方案,我需要添加以下内容:
fun corsConfigurationSource(): CorsConfigurationSource {
val cors = CorsConfiguration()
cors.allowedOrigins = List.of("*")
cors.allowedMethods = List.of("*")
cors.allowedHeaders = List.of("*")
cors.allowCredentials = true
cors.maxAge = 3600L
val source = UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", cors)
return source
}
然后,在我的SecurityWebFilterChain中,我需要让Cors使用我的配置:
@Bean
fun securityFilterChain(
httpSecurity: ServerHttpSecurity
): SecurityWebFilterChain = httpSecurity
.cors(::withConfiguration)
.csrf().disable()
.authorizeExchange()
.pathMatchers("/login", "/register", "/logout").permitAll()
.anyExchange().authenticated()
.and()
.exceptionHandling(::withConfiguration)
.oauth2Login(::withConfiguration)
.logout(::withConfiguration)
.build()
而::withConfiguration解决方案是:
fun withConfiguration(spec: ServerHttpSecurity.CorsSpec): Unit =
spec.configurationSource(corsConfigurationSource())
.run { }