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

Spring Boot(Kotlin)与Angular开发时CORS预检失败求助

问题分析与解决方案

核心问题点

  1. 原CORS配置仅设置路径映射,未明确指定允许的请求源、方法、请求头及凭证携带权限,无法满足浏览器预检请求要求。
  2. SecurityConfig中重复启用httpBasic(),与之前的httpBasic().disable()冲突,干扰CORS配置生效。
  3. 自定义AuthTokenFilter可能拦截了OPTIONS预检请求,未做放行处理。
  4. CorsConfig错误添加@EnableWebMvc,覆盖Spring Boot默认WebMvc自动配置,导致CORS规则不生效。

修正后的配置方案

1. 重新定义CORS配置类

移除@EnableWebMvc,使用CorsConfigurationSource Bean明确配置CORS规则:

@Configuration
class CorsConfig {
    @Bean
    fun corsConfigurationSource(): CorsConfigurationSource {
        val corsConfig = CorsConfiguration()
        // 替换为你的Angular前端开发地址(如http://localhost:4200)
        corsConfig.addAllowedOrigin("http://localhost:4200")
        corsConfig.addAllowedMethod("*")
        corsConfig.addAllowedHeader("*")
        corsConfig.allowCredentials = true
        corsConfig.maxAge = 3600L // 缓存预检请求结果,减少重复OPTIONS请求

        val source = UrlBasedCorsConfigurationSource()
        source.registerCorsConfiguration("/**", corsConfig)
        return source
    }
}

2. 修正SecurityConfig配置

移除重复的httpBasic(),绑定自定义CORS配置源并明确放行OPTIONS请求:

@EnableWebSecurity
@Configuration
class SecurityConfig @Autowired constructor(
    private val authTokenFilter: AuthTokenFilter,
    private val corsConfigurationSource: CorsConfigurationSource
){

    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http
            .httpBasic().disable()
            .csrf().disable()
            // 指定使用自定义CORS配置
            .cors { it.configurationSource(corsConfigurationSource) }
            .authorizeRequests { auth ->
                auth
                    .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行预检请求
                    .anyRequest().permitAll()
            }

        // 将Token过滤器放在认证过滤器前执行
        http.addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter::class.java)
        return http.build()
    }
}

3. 确保AuthTokenFilter放行OPTIONS请求

在自定义过滤器中添加判断,直接放行OPTIONS预检请求:

override fun doFilterInternal(
    request: HttpServletRequest,
    response: HttpServletResponse,
    filterChain: FilterChain
) {
    // 直接放行OPTIONS请求
    if (HttpMethod.OPTIONS.name == request.method) {
        response.status = HttpServletResponse.SC_OK
        filterChain.doFilter(request, response)
        return
    }
    // 你的Token校验逻辑...
    super.doFilterInternal(request, response, filterChain)
}

开发环境临时禁用CORS(不推荐生产使用)

如果只是开发阶段临时测试,可添加全局Filter强制允许所有跨域请求:

@Configuration
class DisableCorsFilter {
    @Bean
    fun corsFilter(): Filter {
        return Filter { request, response, chain ->
            val res = response as HttpServletResponse
            res.setHeader("Access-Control-Allow-Origin", "*")
            res.setHeader("Access-Control-Allow-Methods", "*")
            res.setHeader("Access-Control-Allow-Headers", "*")
            res.setHeader("Access-Control-Max-Age", "3600")
            if (HttpMethod.OPTIONS.name == request.method) {
                res.status = HttpServletResponse.SC_OK
            } else {
                chain.doFilter(request, response)
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 00:05:23