I used Kotlin for my development. First, rewrite the BasicAuthenticationFilter class, I used the JWT to check the token, When the token is invalid, I throw an exception and put it in HttpRequestAttribute.
class JwtAuthorizationFilter(authenticationManager: AuthenticationManager) : BasicAuthenticationFilter(authenticationManager) {
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
// check JWT,and put MyException in HttpRequestAttribute,then throw BadCredentialsException
request.setAttribute("myException", Exception("Invalid token"))
throw BadCredentialsException("")
}
}
Second, implement the AuthenticationEntryPoint interface, I write the exception information here to HttpResponse.
class AuthenticationEntryPointHandle : AuthenticationEntryPoint {
private val httpRequest: HttpServletRequest?
get() = (RequestContextHolder.currentRequestAttributes() as? ServletRequestAttributes)?.request
override fun commence(request: HttpServletRequest?, response: HttpServletResponse, authException: AuthenticationException) {
val myException = httpRequest?.getAttribute("myException") as? Exception
response.status = 401
response.characterEncoding = "UTF-8"
response.contentType = "application/json; charset=utf-8"
val jsonStr = JSONUtil.toJsonStr(myException)
response.writer.println(jsonStr)
}
}
In the end, Configure CorsFilter in the WebSecurityConfigurerAdapter class
@EnableWebSecurity
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
@Autowired
private lateinit var authenticationEntryPointHandle: AuthenticationEntryPointHandle
override fun configure(http: HttpSecurity) {
http.cors().and().csrf().disable()
.and().authorizeRequests().anyRequest().authenticated()
.and().addFilter(JwtAuthorizationFilter(authenticationManagerBean()))
.exceptionHandling {
it.authenticationEntryPoint(authenticationEntryPointHandle)
}
}
@Bean
fun corsFilter(): CorsFilter {
val source = UrlBasedCorsConfigurationSource()
val corsConfiguration = CorsConfiguration()
corsConfiguration.allowedOriginPatterns = listOf("*")
corsConfiguration.addAllowedHeader("*")
corsConfiguration.addAllowedMethod("*")
corsConfiguration.allowCredentials = true
source.registerCorsConfiguration("/**", corsConfiguration)
return CorsFilter(source)
}
}
Normally, this configuration does not cause cross-domain problems, But when token fails, I throw an Exception, The browser will intercept the HttpRespose information and processes it across domains:
Access to XMLHttpRequest at 'a' from origin 'b' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
I guess this is because CorsFilter can only handle HttpRequest, I suggest that CorsFilter can also be processed HttpResponse.
Comment From: tmt1995
I have now solved this problem by modifying the writing method of HttpReponse:
fun writeExceptionInResponse(data: Map<String, Any>, response: HttpServletResponse) {
response.status = data["code"] as? Int ?: 400
response.characterEncoding = "UTF-8"
response.contentType = "application/json; charset=utf-8"
val jsonStr = JSONUtil.toJsonStr(data)
response.setHeader("Access-Control-Allow-Origin", "*")
response.setHeader("Cache-Control", "no-cache")
response.writer.println(jsonStr)
}