Disable CSRF check for PAT authentication (#7353)

#### What type of PR is this?

/kind improvement
/area core
/milestone 2.20.x

#### What this PR does / why we need it:

This PR disables CSRF check for PAT authentication because the authentication won't pass any cookies to server.

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

```release-note
None
```
pull/7364/head
John Niang 2025-04-20 16:18:45 +08:00 committed by GitHub
parent e0b9c50d71
commit 222e955a66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 2 deletions

View File

@ -9,8 +9,11 @@ import org.springframework.security.web.server.csrf.CsrfWebFilter;
import org.springframework.security.web.server.csrf.XorServerCsrfTokenRequestAttributeHandler;
import org.springframework.security.web.server.util.matcher.AndServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.NegatedServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import run.halo.app.security.authentication.SecurityConfigurer;
import run.halo.app.security.authentication.pat.PatAuthenticationConverter;
@Component
@Order(0)
@ -25,7 +28,8 @@ class CsrfConfigurer implements SecurityConfigurer {
"/apis/**",
"/actuator/**",
"/system/setup"
))
)),
new NegatedServerWebExchangeMatcher(patAuthMatcher())
);
http.csrf(csrfSpec -> csrfSpec
.csrfTokenRepository(new CookieServerCsrfTokenRepository())
@ -33,4 +37,11 @@ class CsrfConfigurer implements SecurityConfigurer {
.requireCsrfProtectionMatcher(csrfMatcher));
}
private static ServerWebExchangeMatcher patAuthMatcher() {
var patConverter = new PatAuthenticationConverter();
return exchange -> patConverter.convert(exchange)
.flatMap(a -> ServerWebExchangeMatcher.MatchResult.match())
.switchIfEmpty(Mono.defer(ServerWebExchangeMatcher.MatchResult::notMatch));
}
}

View File

@ -15,7 +15,7 @@ import reactor.core.publisher.Mono;
* @author johnniang
* @since 2.20.4
*/
class PatAuthenticationConverter extends ServerBearerTokenAuthenticationConverter {
public class PatAuthenticationConverter extends ServerBearerTokenAuthenticationConverter {
@Override
public Mono<Authentication> convert(ServerWebExchange exchange) {

View File

@ -0,0 +1,29 @@
package run.halo.app.security;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest
@AutoConfigureWebTestClient
class CsrfSecurityTest {
@Autowired
WebTestClient webClient;
@Test
void shouldNotCheckCsrfForPatAuthentication() {
webClient.post()
.uri("/fake")
.headers(headers -> headers.setBearerAuth("pat_invalid"))
.exchange()
.expectStatus()
.isUnauthorized()
.expectHeader()
.exists(HttpHeaders.WWW_AUTHENTICATE);
}
}