You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data Rest+Spring Security下/login路径POST请求CORS异常排查

问题根因
  • 你之前通过RepositoryRestConfigurer配置的CORS规则仅生效于Spring Data Rest暴露的资源接口,/login请求由Spring Security过滤器链直接处理,不会走到Spring Data Rest的CORS处理逻辑。
  • 浏览器对跨域非简单请求(比如JSON格式提交的POST登录请求)会先发送OPTIONS方法的预检请求,当前安全配置既没有在过滤器链前置CORS响应头逻辑,也没有对OPTIONS请求放行,导致预检请求被拦截,触发跨域报错。
  • iOS、Android移动端原生请求不受浏览器同源策略约束,不会发送CORS预检请求,因此不受该问题影响。
修复步骤

1. 注册全局CORS配置源,开启Spring Security层的CORS支持

首先在你的安全配置类(或者任意配置类)中注册CorsConfigurationSource类型的Bean,定义全局生效的CORS规则,Spring Security会自动将CORS过滤器排在所有认证过滤器之前执行,确保CORS响应头在所有认证逻辑之前返回:

@Bean
fun corsConfigurationSource(): CorsConfigurationSource {
    val corsConfig = CorsConfiguration().apply {
        // 按需调整允许的源、方法、头配置
        allowedOriginPatterns = listOf("http://localhost:[*]")
        allowedMethods = listOf("GET", "POST", "PUT", "DELETE", "OPTIONS")
        allowedHeaders = listOf("*")
        // 要把自定义的Authorization响应头暴露给前端,否则前端拿不到token
        exposedHeaders = listOf("Authorization", "Content-Type")
        allowCredentials = true
    }
    return UrlBasedCorsConfigurationSource().apply {
        registerCorsConfiguration("/**", corsConfig)
    }
}

然后在AppWebSecurityConfigurerAdapter的http配置块中,和csrf、sessionManagement配置同层级添加CORS开启配置:

http {
    csrf { disable() }
    // 新增这行开启Security层CORS支持
    cors { }
    sessionManagement {
        sessionCreationPolicy = SessionCreationPolicy.STATELESS
    }
    // 其余原有过滤器、权限配置保持不变
    addFilterAt<UsernamePasswordAuthenticationFilter>(
        JwtUsernameAndPasswordAuthenticationFilter(
            authenticationManager(),
            jwtConfiguration,
            secretKey,
            repository
        )
    )
    addFilterAfter<JwtUsernameAndPasswordAuthenticationFilter>(JwtTokenVerifier(jwtConfiguration, secretKey))
    authorizeRequests {
        authorize(anyRequest, permitAll)
    }
}

2. 放行所有OPTIONS预检请求

在authorizeRequests配置块最前面添加规则,允许所有OPTIONS请求直接通过,不需要走认证逻辑:

authorizeRequests {
    // 新增这行,优先放行预检请求
    authorize(HttpMethod.OPTIONS, "/**", permitAll)
    authorize(anyRequest, permitAll)
}

3. (可选兜底)自定义登录过滤器跳过OPTIONS请求

为了避免极端情况下CORS过滤器未拦截到OPTIONS请求,导致登录过滤器尝试解析空请求体报错,可以在JwtUsernameAndPasswordAuthenticationFilter的attemptAuthentication方法最开头加判断,直接放行OPTIONS请求:

override fun attemptAuthentication(request: HttpServletRequest?, response: HttpServletResponse?): Authentication {
    // 新增开头判断
    if (request?.method == HttpMethod.OPTIONS.name()) {
        response?.status = HttpServletResponse.SC_OK
        // 直接返回空认证对象,不执行后续登录逻辑
        return UsernamePasswordAuthenticationToken(null, null)
    }
    // 原有解析请求体、认证逻辑保持不变
    val authenticationRequest: UsernameAndPasswordAuthenticationRequest? =
        request?.inputStream?.let { jacksonObjectMapper().readValue(it) }
    return authenticationManager.authenticate(
        UsernamePasswordAuthenticationToken(authenticationRequest?.username, authenticationRequest?.password)
    )
}

改完重启服务,Web端的/login跨域问题即可解决。

内容的提问来源于stack exchange,提问作者gd08xxx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:01:11