Skip to content

Commit

Permalink
Support customizing CORS configuration (#6981)
Browse files Browse the repository at this point in the history
#### 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
支持自定义跨域配置
```
  • Loading branch information
JohnNiang authored Oct 31, 2024
1 parent 0c1849f commit 4dbfb93
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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();
Expand All @@ -43,6 +46,24 @@ public static class TwoFactorAuthOptions {

}

@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
public static class FrameOptions {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,46 @@
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(
List.of(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE, HttpHeaders.ACCEPT,
"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;
Expand Down

0 comments on commit 4dbfb93

Please sign in to comment.