yeg
2026-09-14 d7ea23ab5de44dc7c84a0cde255abd91981c8512
talent-card-server/src/main/java/com/talentcard/server/config/ApiCorsConfig.java
@@ -13,10 +13,14 @@
@Configuration
public class ApiCorsConfig {
    @Bean
    public CorsFilter apiCorsFilter(@Value("${app.cors.allowed-origins:}") String allowedOrigins) {
    public CorsFilter apiCorsFilter(
            @Value("${app.cors.allowed-origins:}") String allowedOrigins,
            @Value("${app.cors.allowed-origin-patterns:}") String allowedOriginPatterns) {
        CorsConfiguration cors = new CorsConfiguration();
        cors.setAllowedOrigins(Arrays.stream(allowedOrigins.split(","))
                .map(String::trim).filter(origin -> !origin.isEmpty()).toList());
        cors.setAllowedOrigins(split(allowedOrigins));
        // 本地开发工具的端口是随机的(微信开发者工具每次启动都换一个),写死端口必然漏。
        // 用 origin 通配覆盖本机各种调试端口,真实域名仍走上面的精确白名单。
        cors.setAllowedOriginPatterns(split(allowedOriginPatterns));
        cors.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        cors.setAllowedHeaders(List.of("Content-Type", "Authorization", "X-Request-Id",
                "X-Client-Platform", "X-Client-Version", "X-Merchant-Store-Id", "X-Idempotency-Key"));
@@ -27,4 +31,8 @@
        // Complete browser preflight before MVC authentication interceptors run.
        return new CorsFilter(source);
    }
    private static List<String> split(String values) {
        return Arrays.stream(values.split(",")).map(String::trim).filter(value -> !value.isEmpty()).toList();
    }
}