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)
}