diff --git a/api/src/main/java/run/halo/app/security/AfterSecurityWebFilter.java b/api/src/main/java/run/halo/app/security/AfterSecurityWebFilter.java new file mode 100644 index 0000000000..c012110403 --- /dev/null +++ b/api/src/main/java/run/halo/app/security/AfterSecurityWebFilter.java @@ -0,0 +1,14 @@ +package run.halo.app.security; + +import org.pf4j.ExtensionPoint; +import org.springframework.web.server.WebFilter; + +/** + * Security web filter for after security. + * + * @author johnniang + * @since 2.18 + */ +public interface AfterSecurityWebFilter extends WebFilter, ExtensionPoint { + +} diff --git a/api/src/main/java/run/halo/app/security/BeforeSecurityWebFilter.java b/api/src/main/java/run/halo/app/security/BeforeSecurityWebFilter.java new file mode 100644 index 0000000000..0bedc3dd88 --- /dev/null +++ b/api/src/main/java/run/halo/app/security/BeforeSecurityWebFilter.java @@ -0,0 +1,14 @@ +package run.halo.app.security; + +import org.pf4j.ExtensionPoint; +import org.springframework.web.server.WebFilter; + +/** + * Security web filter for before security. + * + * @author johnniang + * @since 2.18 + */ +public interface BeforeSecurityWebFilter extends WebFilter, ExtensionPoint { + +} diff --git a/application/src/main/java/run/halo/app/security/SecurityWebFiltersConfigurer.java b/application/src/main/java/run/halo/app/security/SecurityWebFiltersConfigurer.java index 0cf5a38fc7..daef125f6a 100644 --- a/application/src/main/java/run/halo/app/security/SecurityWebFiltersConfigurer.java +++ b/application/src/main/java/run/halo/app/security/SecurityWebFiltersConfigurer.java @@ -2,7 +2,9 @@ import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.ANONYMOUS_AUTHENTICATION; import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.AUTHENTICATION; +import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.FIRST; import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.FORM_LOGIN; +import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.LAST; import lombok.Setter; import org.pf4j.ExtensionPoint; @@ -30,7 +32,12 @@ public SecurityWebFiltersConfigurer(ExtensionGetter extensionGetter) { public void configure(ServerHttpSecurity http) { http .addFilterAt( - new SecurityWebFilterChainProxy(FormLoginSecurityWebFilter.class), FORM_LOGIN + new SecurityWebFilterChainProxy(BeforeSecurityWebFilter.class), + FIRST + ) + .addFilterAt( + new SecurityWebFilterChainProxy(FormLoginSecurityWebFilter.class), + FORM_LOGIN ) .addFilterAt( new SecurityWebFilterChainProxy(AuthenticationSecurityWebFilter.class), @@ -39,7 +46,12 @@ public void configure(ServerHttpSecurity http) { .addFilterAt( new SecurityWebFilterChainProxy(AnonymousAuthenticationSecurityWebFilter.class), ANONYMOUS_AUTHENTICATION - ); + ) + .addFilterAt( + new SecurityWebFilterChainProxy(AfterSecurityWebFilter.class), + LAST + ) + ; } public class SecurityWebFilterChainProxy implements WebFilter { diff --git a/docs/extension-points/authentication.md b/docs/extension-points/authentication.md index d471b2b2ed..a97db1b29b 100644 --- a/docs/extension-points/authentication.md +++ b/docs/extension-points/authentication.md @@ -27,6 +27,7 @@ public class MyFormLoginSecurityWebFilter implements FormLoginSecurityWebFilter } ``` + ## 普通认证(Authentication) 示例如下: @@ -41,11 +42,11 @@ import run.halo.app.security.AuthenticationSecurityWebFilter; @Component public class MyAuthenticationSecurityWebFilter implements AuthenticationSecurityWebFilter { - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - // Do your logic here - return chain.filter(exchange); - } + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + // Do your logic here + return chain.filter(exchange); + } } ``` @@ -62,16 +63,56 @@ import run.halo.app.security.AnonymousAuthenticationSecurityWebFilter; @Component public class MyAnonymousAuthenticationSecurityWebFilter - implements AnonymousAuthenticationSecurityWebFilter { + implements AnonymousAuthenticationSecurityWebFilter { + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + // Do your logic here + return chain.filter(exchange); + } +} +``` + +## 前置过滤器(BeforeSecurityWebFilter) + +主要用于在进行认证之前的一些处理。需要注意的是,当前过滤器中无法直接通过 ReactiveSecurityContextHolder 获取 +SecurityContext。示例如下: + +```java +public class MyBeforeSecurityWebFilter implements BeforeSecurityWebFilter { - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - // Do your logic here - return chain.filter(exchange); - } + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + // Do your logic here + return chain.filter(exchange); + } } ``` +## 后置过滤器(AfterSecurityWebFilter) + +主要用于进行认证之后的一些处理。在当前过滤器中,可以通过 ReactiveSecurityContextHolder 获取 SecurityContext。示例如下: + +```java +public class MyAfterSecurityWebFilter implements AfterSecurityWebFilter { + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + return ReactiveSecurityContextHolder.getContext() + .switchIfEmpty(Mono.defer(() -> { + // do something... + return chain.filter(exchange).then(Mono.empty()); + })) + .flatMap(securityContext -> { + // do something... + return chain.filter(exchange); + }); + } +} +``` + +--- + 我们在实现扩展点的时候需要注意:如果当前请求不满足认证条件,请一定要调用 `chain.filter(exchange)`,给其他 filter 留下机会。 后续会根据需求实现其他认证相关的扩展点。 \ No newline at end of file