diff --git a/application/src/main/java/run/halo/app/config/WebFluxConfig.java b/application/src/main/java/run/halo/app/config/WebFluxConfig.java
index 7bb8f6193..a0ad4bd61 100644
--- a/application/src/main/java/run/halo/app/config/WebFluxConfig.java
+++ b/application/src/main/java/run/halo/app/config/WebFluxConfig.java
@@ -15,6 +15,7 @@ import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
@@ -40,6 +41,8 @@ import run.halo.app.console.WebSocketRequestPredicate;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
import run.halo.app.infra.properties.HaloProperties;
+import run.halo.app.plugin.extensionpoint.ExtensionGetter;
+import run.halo.app.webfilter.AdditionalWebFilterChainProxy;
@Configuration
public class WebFluxConfig implements WebFluxConfigurer {
@@ -200,4 +203,23 @@ public class WebFluxConfig implements WebFluxConfigurer {
ProxyFilter ucProxyFilter() {
return new ProxyFilter("/uc/**", haloProp.getUc().getProxy());
}
+
+ /**
+ * Create a WebFilterChainProxy for all AdditionalWebFilters.
+ *
+ *
The reason why the order is -101 is that the current
+ * AdditionalWebFilterChainProxy should be executed before WebFilterChainProxy
+ * and the order of WebFilterChainProxy is -100.
+ *
+ *
See {@code org.springframework.security.config.annotation.web.reactive
+ * .WebFluxSecurityConfiguration#WEB_FILTER_CHAIN_FILTER_ORDER} for more
+ *
+ * @param extensionGetter extension getter.
+ * @return additional web filter chain proxy.
+ */
+ @Bean
+ @Order(-101)
+ AdditionalWebFilterChainProxy additionalWebFilterChainProxy(ExtensionGetter extensionGetter) {
+ return new AdditionalWebFilterChainProxy(extensionGetter);
+ }
}
diff --git a/application/src/main/java/run/halo/app/config/WebServerSecurityConfig.java b/application/src/main/java/run/halo/app/config/WebServerSecurityConfig.java
index 6d1a5d4ce..17af565dc 100644
--- a/application/src/main/java/run/halo/app/config/WebServerSecurityConfig.java
+++ b/application/src/main/java/run/halo/app/config/WebServerSecurityConfig.java
@@ -30,9 +30,7 @@ import run.halo.app.core.extension.service.UserService;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.AnonymousUserConst;
import run.halo.app.infra.properties.HaloProperties;
-import run.halo.app.plugin.extensionpoint.ExtensionGetter;
import run.halo.app.security.DefaultUserDetailService;
-import run.halo.app.security.DynamicMatcherSecurityWebFilterChain;
import run.halo.app.security.authentication.SecurityConfigurer;
import run.halo.app.security.authentication.login.CryptoService;
import run.halo.app.security.authentication.login.PublicKeyRouteBuilder;
@@ -60,7 +58,6 @@ public class WebServerSecurityConfig {
RoleService roleService,
ObjectProvider securityConfigurers,
ServerSecurityContextRepository securityContextRepository,
- ExtensionGetter extensionGetter,
ReactiveExtensionClient client,
PatJwkSupplier patJwkSupplier) {
@@ -92,7 +89,7 @@ public class WebServerSecurityConfig {
// Integrate with other configurers separately
securityConfigurers.orderedStream()
.forEach(securityConfigurer -> securityConfigurer.configure(http));
- return new DynamicMatcherSecurityWebFilterChain(extensionGetter, http.build());
+ return http.build();
}
@Bean
diff --git a/application/src/main/java/run/halo/app/security/DynamicMatcherSecurityWebFilterChain.java b/application/src/main/java/run/halo/app/security/DynamicMatcherSecurityWebFilterChain.java
deleted file mode 100644
index 45095f26f..000000000
--- a/application/src/main/java/run/halo/app/security/DynamicMatcherSecurityWebFilterChain.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package run.halo.app.security;
-
-import org.springframework.core.Ordered;
-import org.springframework.core.annotation.AnnotationAwareOrderComparator;
-import org.springframework.lang.NonNull;
-import org.springframework.security.web.server.SecurityWebFilterChain;
-import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
-import org.springframework.web.server.ServerWebExchange;
-import org.springframework.web.server.WebFilter;
-import org.springframework.web.server.WebFilterChain;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import run.halo.app.plugin.extensionpoint.ExtensionGetter;
-
-/**
- * A {@link SecurityWebFilterChain} that leverages a {@link ServerWebExchangeMatcher} to
- * determine which {@link WebFilter} to execute.
- *
- * @author guqing
- * @since 2.4.0
- */
-public class DynamicMatcherSecurityWebFilterChain implements SecurityWebFilterChain {
-
- private final SecurityWebFilterChain delegate;
-
- private final ExtensionGetter extensionGetter;
-
- public DynamicMatcherSecurityWebFilterChain(ExtensionGetter extensionGetter,
- SecurityWebFilterChain delegate) {
- this.delegate = delegate;
- this.extensionGetter = extensionGetter;
- }
-
- @Override
- public Mono matches(ServerWebExchange exchange) {
- return delegate.matches(exchange);
- }
-
- @Override
- public Flux getWebFilters() {
- return Flux.merge(delegate.getWebFilters(), getAdditionalFilters())
- .sort(new AnnotationAwareOrderComparator());
- }
-
- private Flux getAdditionalFilters() {
- return extensionGetter.getEnabledExtensionByDefinition(AdditionalWebFilter.class)
- .map(additionalWebFilter -> new OrderedWebFilter(additionalWebFilter,
- additionalWebFilter.getOrder())
- );
- }
-
- private record OrderedWebFilter(WebFilter webFilter, int order) implements WebFilter, Ordered {
-
- @Override
- @NonNull
- public Mono filter(@NonNull ServerWebExchange exchange,
- @NonNull WebFilterChain chain) {
- return this.webFilter.filter(exchange, chain);
- }
-
- @Override
- public int getOrder() {
- return this.order;
- }
- }
-}
diff --git a/application/src/main/java/run/halo/app/webfilter/AdditionalWebFilterChainProxy.java b/application/src/main/java/run/halo/app/webfilter/AdditionalWebFilterChainProxy.java
new file mode 100644
index 000000000..7952bc113
--- /dev/null
+++ b/application/src/main/java/run/halo/app/webfilter/AdditionalWebFilterChainProxy.java
@@ -0,0 +1,35 @@
+package run.halo.app.webfilter;
+
+import lombok.Setter;
+import org.springframework.core.annotation.AnnotationAwareOrderComparator;
+import org.springframework.security.web.server.WebFilterChainProxy;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
+import run.halo.app.plugin.extensionpoint.ExtensionGetter;
+import run.halo.app.security.AdditionalWebFilter;
+
+public class AdditionalWebFilterChainProxy implements WebFilter {
+
+ private final ExtensionGetter extensionGetter;
+
+ @Setter
+ private WebFilterChainProxy.WebFilterChainDecorator filterChainDecorator;
+
+ public AdditionalWebFilterChainProxy(ExtensionGetter extensionGetter) {
+ this.extensionGetter = extensionGetter;
+ this.filterChainDecorator = new WebFilterChainProxy.DefaultWebFilterChainDecorator();
+ }
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, WebFilterChain chain) {
+ return extensionGetter.getEnabledExtensionByDefinition(AdditionalWebFilter.class)
+ .sort(AnnotationAwareOrderComparator.INSTANCE)
+ .cast(WebFilter.class)
+ .collectList()
+ .map(filters -> filterChainDecorator.decorate(chain, filters))
+ .flatMap(decoratedChain -> decoratedChain.filter(exchange));
+ }
+
+}