mirror of https://github.com/halo-dev/halo
Add before and after security web filters (#6297)
#### What type of PR is this? /kind feature /kind api-change /area core /area plugin #### What this PR does / why we need it: This PR adds `BeforeSecurityWebFilter` and `AfterSecurityWebFilter` extension points. See https://github.com/halo-sigs/plugin-page-cache/issues/4#issuecomment-2216677891 for more. Now, we can do something before and after authenticating. #### Does this PR introduce a user-facing change? ```release-note 添加认证授权的前置和后置处理器扩展点 ```pull/6265/head^2
parent
0f01006606
commit
9cdd8a5301
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,9 @@ package run.halo.app.security;
|
||||||
|
|
||||||
import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.ANONYMOUS_AUTHENTICATION;
|
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.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.FORM_LOGIN;
|
||||||
|
import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.LAST;
|
||||||
|
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.pf4j.ExtensionPoint;
|
import org.pf4j.ExtensionPoint;
|
||||||
|
@ -30,7 +32,12 @@ public class SecurityWebFiltersConfigurer implements SecurityConfigurer {
|
||||||
public void configure(ServerHttpSecurity http) {
|
public void configure(ServerHttpSecurity http) {
|
||||||
http
|
http
|
||||||
.addFilterAt(
|
.addFilterAt(
|
||||||
new SecurityWebFilterChainProxy(FormLoginSecurityWebFilter.class), FORM_LOGIN
|
new SecurityWebFilterChainProxy(BeforeSecurityWebFilter.class),
|
||||||
|
FIRST
|
||||||
|
)
|
||||||
|
.addFilterAt(
|
||||||
|
new SecurityWebFilterChainProxy(FormLoginSecurityWebFilter.class),
|
||||||
|
FORM_LOGIN
|
||||||
)
|
)
|
||||||
.addFilterAt(
|
.addFilterAt(
|
||||||
new SecurityWebFilterChainProxy(AuthenticationSecurityWebFilter.class),
|
new SecurityWebFilterChainProxy(AuthenticationSecurityWebFilter.class),
|
||||||
|
@ -39,7 +46,12 @@ public class SecurityWebFiltersConfigurer implements SecurityConfigurer {
|
||||||
.addFilterAt(
|
.addFilterAt(
|
||||||
new SecurityWebFilterChainProxy(AnonymousAuthenticationSecurityWebFilter.class),
|
new SecurityWebFilterChainProxy(AnonymousAuthenticationSecurityWebFilter.class),
|
||||||
ANONYMOUS_AUTHENTICATION
|
ANONYMOUS_AUTHENTICATION
|
||||||
);
|
)
|
||||||
|
.addFilterAt(
|
||||||
|
new SecurityWebFilterChainProxy(AfterSecurityWebFilter.class),
|
||||||
|
LAST
|
||||||
|
)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SecurityWebFilterChainProxy implements WebFilter {
|
public class SecurityWebFilterChainProxy implements WebFilter {
|
||||||
|
|
|
@ -27,6 +27,7 @@ public class MyFormLoginSecurityWebFilter implements FormLoginSecurityWebFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 普通认证(Authentication)
|
## 普通认证(Authentication)
|
||||||
|
|
||||||
示例如下:
|
示例如下:
|
||||||
|
@ -41,11 +42,11 @@ import run.halo.app.security.AuthenticationSecurityWebFilter;
|
||||||
@Component
|
@Component
|
||||||
public class MyAuthenticationSecurityWebFilter implements AuthenticationSecurityWebFilter {
|
public class MyAuthenticationSecurityWebFilter implements AuthenticationSecurityWebFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||||
// Do your logic here
|
// Do your logic here
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -62,16 +63,56 @@ import run.halo.app.security.AnonymousAuthenticationSecurityWebFilter;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class MyAnonymousAuthenticationSecurityWebFilter
|
public class MyAnonymousAuthenticationSecurityWebFilter
|
||||||
implements AnonymousAuthenticationSecurityWebFilter {
|
implements AnonymousAuthenticationSecurityWebFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||||
// Do your logic here
|
// Do your logic here
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 前置过滤器(BeforeSecurityWebFilter)
|
||||||
|
|
||||||
|
主要用于在进行认证之前的一些处理。需要注意的是,当前过滤器中无法直接通过 ReactiveSecurityContextHolder 获取
|
||||||
|
SecurityContext。示例如下:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class MyBeforeSecurityWebFilter implements BeforeSecurityWebFilter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> 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<Void> 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 留下机会。
|
我们在实现扩展点的时候需要注意:如果当前请求不满足认证条件,请一定要调用 `chain.filter(exchange)`,给其他 filter 留下机会。
|
||||||
|
|
||||||
后续会根据需求实现其他认证相关的扩展点。
|
后续会根据需求实现其他认证相关的扩展点。
|
Loading…
Reference in New Issue