| | |
| | | @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")); |
| | |
| | | // 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(); |
| | | } |
| | | } |