Skip to content

Commit

Permalink
Add before and after security web filters (#6297)
Browse files Browse the repository at this point in the history
#### 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 halo-sigs/plugin-page-cache#4 (comment) for more.

Now, we can do something before and after authenticating.

#### Does this PR introduce a user-facing change?

```release-note
添加认证授权的前置和后置处理器扩展点
```
  • Loading branch information
JohnNiang authored Jul 9, 2024
1 parent 0f01006 commit 9cdd8a5
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -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 {

}
Original file line number Diff line number Diff line change
@@ -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 {

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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),
Expand All @@ -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 {
Expand Down
63 changes: 52 additions & 11 deletions docs/extension-points/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class MyFormLoginSecurityWebFilter implements FormLoginSecurityWebFilter
}

```

## 普通认证(Authentication)

示例如下:
Expand All @@ -41,11 +42,11 @@ import run.halo.app.security.AuthenticationSecurityWebFilter;
@Component
public class MyAuthenticationSecurityWebFilter implements AuthenticationSecurityWebFilter {

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
// Do your logic here
return chain.filter(exchange);
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
// Do your logic here
return chain.filter(exchange);
}
}
```

Expand All @@ -62,16 +63,56 @@ import run.halo.app.security.AnonymousAuthenticationSecurityWebFilter;

@Component
public class MyAnonymousAuthenticationSecurityWebFilter
implements AnonymousAuthenticationSecurityWebFilter {
implements AnonymousAuthenticationSecurityWebFilter {

@Override
public Mono<Void> 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<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
// Do your logic here
return chain.filter(exchange);
}
@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 留下机会。

后续会根据需求实现其他认证相关的扩展点。

0 comments on commit 9cdd8a5

Please sign in to comment.