1
0
mirror of synced 2026-08-04 09:17:02 +00:00

Verify ReactorContext when using Virtual Threads

Closes gh-12791
This commit is contained in:
Steve Riesenberg
2023-09-21 10:27:25 -05:00
parent d6fac11bfe
commit ff374935fb
4 changed files with 190 additions and 4 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,17 @@
package org.springframework.security.core.context;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.JRE;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import reactor.test.StepVerifier;
import org.springframework.core.task.VirtualThreadTaskExecutor;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
@@ -99,4 +106,53 @@ public class ReactiveSecurityContextHolderTests {
// @formatter:on
}
@Test
public void getContextWhenThreadFactoryIsPlatformThenPropagated() {
verifySecurityContextIsPropagated(Executors.defaultThreadFactory());
}
@Test
@DisabledOnJre(JRE.JAVA_17)
public void getContextWhenThreadFactoryIsVirtualThenPropagated() {
verifySecurityContextIsPropagated(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
}
private static void verifySecurityContextIsPropagated(ThreadFactory threadFactory) {
Authentication authentication = new TestingAuthenticationToken("user", null);
// @formatter:off
Mono<Authentication> publisher = ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.contextWrite((context) -> ReactiveSecurityContextHolder.withAuthentication(authentication))
.subscribeOn(Schedulers.newSingle(threadFactory));
// @formatter:on
StepVerifier.create(publisher).expectNext(authentication).verifyComplete();
}
@Test
public void clearContextWhenThreadFactoryIsPlatformThenCleared() {
verifySecurityContextIsCleared(Executors.defaultThreadFactory());
}
@Test
@DisabledOnJre(JRE.JAVA_17)
public void clearContextWhenThreadFactoryIsVirtualThenCleared() {
verifySecurityContextIsCleared(new VirtualThreadTaskExecutor().getVirtualThreadFactory());
}
private static void verifySecurityContextIsCleared(ThreadFactory threadFactory) {
Authentication authentication = new TestingAuthenticationToken("user", null);
// @formatter:off
Mono<Authentication> publisher = ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.contextWrite(ReactiveSecurityContextHolder.clearContext())
.contextWrite((context) -> ReactiveSecurityContextHolder.withAuthentication(authentication))
.subscribeOn(Schedulers.newSingle(threadFactory));
// @formatter:on
StepVerifier.create(publisher).verifyComplete();
}
}