Spring Boot 2.7.0 I faced CORS exception that triggered XMLHttpRequestError when trying to post via the '/login' path, other paths such as '/api/v1/members' are fine.
I followed the below guide, https://github.com/amigoscode/spring-boot-security-course/tree/8-JTW
I am currently using SpringDataRest with configuration in RepositoryRestConfigurer as follow
@Component
class AppRepositoryRestConfigurer : RepositoryRestConfigurer {
override fun configureRepositoryRestConfiguration(config: RepositoryRestConfiguration?, cors: CorsRegistry?) {
cors?.addMapping("/**")?.allowedOriginPatterns("http://localhost:[*]")
}
}
Where else do I need to add CORS mapping in order to fulfil the post request via web. Right now posting via mobile app(iOS + Android) is ok with the Flutter framework, but Flutter Web is not ok.
I think the issue might be related to the OncePerRequestFilter? Below is my code from my WebSecurityConfigurerAdapter
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class AppWebSecurityConfigurerAdapter(
private val passwordEncoder: PasswordEncoder,
private val appUserDetailsService: AppUserDetailsService,
private val jwtConfiguration: JwtConfiguration,
private val secretKey: SecretKey,
private val repository: MemberRepository
) : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity?) {
http {
csrf {
disable()
}
sessionManagement {
sessionCreationPolicy = SessionCreationPolicy.STATELESS
}
addFilterAt<UsernamePasswordAuthenticationFilter>(
JwtUsernameAndPasswordAuthenticationFilter(
authenticationManager(),
jwtConfiguration,
secretKey,
repository
)
)
addFilterAfter<JwtUsernameAndPasswordAuthenticationFilter>(JwtTokenVerifier(jwtConfiguration, secretKey))
authorizeRequests {
authorize(anyRequest, permitAll)
}
}
}
override fun configure(auth: AuthenticationManagerBuilder?) {
auth?.authenticationProvider(daoAuthenticationProvider())
}
@Bean
fun daoAuthenticationProvider() =
DaoAuthenticationProvider().apply {
setPasswordEncoder(passwordEncoder)
setUserDetailsService(appUserDetailsService)
}
}
My code for UsernameAndPasswordAuthenticationFilter
class JwtUsernameAndPasswordAuthenticationFilter(
authenticationManager: AuthenticationManager,
private val configuration: JwtConfiguration,
private val secretKey: SecretKey,
private val repository: MemberRepository
) : UsernamePasswordAuthenticationFilter(authenticationManager) {
private val objectMapper = jacksonObjectMapper().apply {
registerModule(JavaTimeModule())
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
}
override fun attemptAuthentication(request: HttpServletRequest?, response: HttpServletResponse?): Authentication {
val authenticationRequest: UsernameAndPasswordAuthenticationRequest? =
request?.inputStream?.let { jacksonObjectMapper().readValue(it) }
return authenticationManager.authenticate(
UsernamePasswordAuthenticationToken(authenticationRequest?.username, authenticationRequest?.password)
)
}
override fun successfulAuthentication(
request: HttpServletRequest?,
response: HttpServletResponse?,
chain: FilterChain?,
authResult: Authentication?
) {
val token = Jwts.builder()
.setSubject(authResult?.name)
.claim("authorities", authResult?.authorities)
.setIssuedAt(Date())
.setExpiration(java.sql.Date.valueOf(LocalDate.now().plusDays(configuration.daysToExpire)))
.signWith(secretKey)
.compact()
val body = objectMapper.writeValueAsString(authResult?.name?.let(repository::findByEmail))
response?.apply {
addHeader(configuration.authorizationHeader, "${configuration.tokenPrefix} $token")
addHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf-8")
writer.write(body)
}
}
}
App.kt
@SpringBootApplication
@ConfigurationPropertiesScan
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
Much help is appreciated:)
I figured out the issue. This relates to the cors configuration in Spring Security. If you use web, the browser changed the POST request into an OPTIONS request, therefore blocked by the default CORS configuration because there default does not allow OPTION requests
override fun configure(http: HttpSecurity?) {
http {
csrf {
disable()
}
cors {} //Enable CORS here
sessionManagement {
sessionCreationPolicy = SessionCreationPolicy.STATELESS
}
addFilterAt<UsernamePasswordAuthenticationFilter>(
JwtUsernameAndPasswordAuthenticationFilter(
authenticationManager(),
jwtConfiguration,
secretKey,
repository
)
)
addFilterAfter<JwtUsernameAndPasswordAuthenticationFilter>(JwtTokenVerifier(jwtConfiguration, secretKey))
authorizeRequests {
authorize(anyRequest, permitAll)
}
}
}
Configure your CORS here
@Bean
fun corsConfigurationSource(): CorsConfigurationSource {
val configuration = CorsConfiguration()
configuration.allowedOrigins = listOf("https://example.com")
configuration.allowedMethods = listOf("*") //Allow all http methods
val source = UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", configuration)
return source
}
This is no longer needed after implementing CORS in Spring Security
@Component
class AppRepositoryRestConfigurer : RepositoryRestConfigurer {
override fun configureRepositoryRestConfiguration(config: RepositoryRestConfiguration?, cors: CorsRegistry?) {
cors?.addMapping("/**")?.allowedOriginPatterns("http://localhost:[*]")
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.