mirror of https://github.com/halo-dev/halo
Support customizing CORS configuration (#6981)
#### What type of PR is this? /kind improvement /area core /milestone 2.20.x #### What this PR does / why we need it: This PR adds CorsOptions into SecurityProperties to let users customize their own CORS configuration. e.g.: ```yaml halo: security: cors-options: disabled: false configs: - pathPattern: /apis/first.api.halo.run/v1alpha1/** config: allowedOrigins: [ "*" ] allowedHeaders: [ "*" ] allowedMethods: [ "*" ] exposedHeaders: [ "*" ] allowCredentials: true maxAge: 30m - pathPattern: /apis/second.api.halo.run/v1alpha1/** config: allowedOrigins: [ "www.halo.run", "www.lxware.cn" ] allowedHeaders: [ "Content-Type", "Authorization" ] allowedMethods: [ "GET, POST, PUT, DELETE" ] allowedCredentials: false maxAge: 1h ``` #### Does this PR introduce a user-facing change? ```release-note 支持自定义跨域配置 ```pull/7010/head
parent
0c1849fdd5
commit
4dbfb930bf
|
@ -7,6 +7,7 @@ import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.Data;
|
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.ReferrerPolicyServerHttpHeadersWriter.ReferrerPolicy;
|
||||||
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter.Mode;
|
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter.Mode;
|
||||||
|
|
||||||
|
@ -17,6 +18,8 @@ public class SecurityProperties {
|
||||||
|
|
||||||
private final ReferrerOptions referrerOptions = new ReferrerOptions();
|
private final ReferrerOptions referrerOptions = new ReferrerOptions();
|
||||||
|
|
||||||
|
private final CorsOptions corsOptions = new CorsOptions();
|
||||||
|
|
||||||
private final RememberMeOptions rememberMe = new RememberMeOptions();
|
private final RememberMeOptions rememberMe = new RememberMeOptions();
|
||||||
|
|
||||||
private final TwoFactorAuthOptions twoFactorAuth = new TwoFactorAuthOptions();
|
private final TwoFactorAuthOptions twoFactorAuth = new TwoFactorAuthOptions();
|
||||||
|
@ -43,6 +46,24 @@ public class SecurityProperties {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class CorsOptions {
|
||||||
|
|
||||||
|
private boolean disabled;
|
||||||
|
|
||||||
|
private final List<CorsConfig> configs = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class CorsConfig {
|
||||||
|
|
||||||
|
private String pathPattern;
|
||||||
|
|
||||||
|
private CorsEndpointProperties config;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class FrameOptions {
|
public static class FrameOptions {
|
||||||
|
|
||||||
|
|
|
@ -8,17 +8,39 @@ import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.reactive.CorsConfigurationSource;
|
import org.springframework.web.cors.reactive.CorsConfigurationSource;
|
||||||
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
|
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;
|
import run.halo.app.security.authentication.SecurityConfigurer;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Order(0)
|
@Order(0)
|
||||||
public class CorsConfigurer implements SecurityConfigurer {
|
public class CorsConfigurer implements SecurityConfigurer {
|
||||||
|
|
||||||
|
private final SecurityProperties.CorsOptions corsOptions;
|
||||||
|
|
||||||
|
public CorsConfigurer(HaloProperties haloProperties) {
|
||||||
|
corsOptions = haloProperties.getSecurity().getCorsOptions();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(ServerHttpSecurity http) {
|
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() {
|
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();
|
var configuration = new CorsConfiguration();
|
||||||
configuration.setAllowedOriginPatterns(List.of("*"));
|
configuration.setAllowedOriginPatterns(List.of("*"));
|
||||||
configuration.setAllowedHeaders(
|
configuration.setAllowedHeaders(
|
||||||
|
@ -26,8 +48,6 @@ public class CorsConfigurer implements SecurityConfigurer {
|
||||||
"X-XSRF-TOKEN", HttpHeaders.COOKIE));
|
"X-XSRF-TOKEN", HttpHeaders.COOKIE));
|
||||||
configuration.setAllowCredentials(true);
|
configuration.setAllowCredentials(true);
|
||||||
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH"));
|
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH"));
|
||||||
|
|
||||||
var source = new UrlBasedCorsConfigurationSource();
|
|
||||||
source.registerCorsConfiguration("/api/**", configuration);
|
source.registerCorsConfiguration("/api/**", configuration);
|
||||||
source.registerCorsConfiguration("/apis/**", configuration);
|
source.registerCorsConfiguration("/apis/**", configuration);
|
||||||
return source;
|
return source;
|
||||||
|
|
Loading…
Reference in New Issue