From 88e2f694f23587714db4d66e3ded531c48cc85af Mon Sep 17 00:00:00 2001 From: JohnNiang Date: Thu, 31 Oct 2024 16:39:16 +0800 Subject: [PATCH] Support customizing CORS configuration Signed-off-by: JohnNiang --- .../infra/properties/SecurityProperties.java | 21 +++++++++++++++ .../run/halo/app/security/CorsConfigurer.java | 26 ++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/run/halo/app/infra/properties/SecurityProperties.java b/application/src/main/java/run/halo/app/infra/properties/SecurityProperties.java index 5911ac2846..adaf070a0e 100644 --- a/application/src/main/java/run/halo/app/infra/properties/SecurityProperties.java +++ b/application/src/main/java/run/halo/app/infra/properties/SecurityProperties.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.List; import lombok.Data; +import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties; import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter.ReferrerPolicy; import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter.Mode; @@ -17,6 +18,8 @@ public class SecurityProperties { private final ReferrerOptions referrerOptions = new ReferrerOptions(); + private final CorsOptions corsOptions = new CorsOptions(); + private final RememberMeOptions rememberMe = new RememberMeOptions(); private final TwoFactorAuthOptions twoFactorAuth = new TwoFactorAuthOptions(); @@ -43,6 +46,24 @@ public static class TwoFactorAuthOptions { } + @Data + public static class CorsOptions { + + private boolean disabled; + + private final List configs = new ArrayList<>(); + + } + + @Data + public static class CorsConfig { + + private String pathPattern; + + private CorsEndpointProperties config; + + } + @Data public static class FrameOptions { diff --git a/application/src/main/java/run/halo/app/security/CorsConfigurer.java b/application/src/main/java/run/halo/app/security/CorsConfigurer.java index dc91f21797..58b1559232 100644 --- a/application/src/main/java/run/halo/app/security/CorsConfigurer.java +++ b/application/src/main/java/run/halo/app/security/CorsConfigurer.java @@ -8,17 +8,39 @@ import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsConfigurationSource; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; +import run.halo.app.infra.properties.HaloProperties; +import run.halo.app.infra.properties.SecurityProperties; import run.halo.app.security.authentication.SecurityConfigurer; @Component @Order(0) public class CorsConfigurer implements SecurityConfigurer { + + private final SecurityProperties.CorsOptions corsOptions; + + public CorsConfigurer(HaloProperties haloProperties) { + corsOptions = haloProperties.getSecurity().getCorsOptions(); + } + @Override public void configure(ServerHttpSecurity http) { - http.cors(spec -> spec.configurationSource(apiCorsConfigSource())); + http.cors(spec -> { + if (corsOptions.isDisabled()) { + spec.disable(); + return; + } + spec.configurationSource(apiCorsConfigSource()); + }); } CorsConfigurationSource apiCorsConfigSource() { + var source = new UrlBasedCorsConfigurationSource(); + // additional CORS configuration + this.corsOptions.getConfigs().forEach(corsConfig -> source.registerCorsConfiguration( + corsConfig.getPathPattern(), corsConfig.getConfig().toCorsConfiguration() + )); + + // default CORS configuration var configuration = new CorsConfiguration(); configuration.setAllowedOriginPatterns(List.of("*")); configuration.setAllowedHeaders( @@ -26,8 +48,6 @@ CorsConfigurationSource apiCorsConfigSource() { "X-XSRF-TOKEN", HttpHeaders.COOKIE)); configuration.setAllowCredentials(true); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH")); - - var source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/api/**", configuration); source.registerCorsConfiguration("/apis/**", configuration); return source;