Split into per-article modules and add the method-security module
Moves the existing virtual-thread/context-propagation project into context-propagation/ and adds method-security/ for the Spring Security 7 method-security article: nine runnable demos, fourteen assertions, and every transcript the article quotes, regenerated by scripts/run-all.sh. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RSrsDSRKVsY588yFiMJMo9
This commit is contained in:
5
context-propagation/docs/output/demo1.txt
Normal file
5
context-propagation/docs/output/demo1.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
=== Demo 1: InheritableThreadLocal across thread models ===
|
||||
fresh platform thread sees: request-A
|
||||
pool thread, task 1, sees: request-B
|
||||
pool thread, task 2 (reused), sees: request-B <-- stale, not request-C
|
||||
fresh virtual thread sees: request-D
|
||||
6
context-propagation/docs/output/demo2.txt
Normal file
6
context-propagation/docs/output/demo2.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
=== Demo 2: @Async-style virtual thread executor + SecurityContext ===
|
||||
A) MODE_THREADLOCAL, raw SimpleAsyncTaskExecutor(virtual): NO AUTHENTICATION (lost) [VirtualThread[#23,vt-1]/runnable@ForkJoinPool-1-worker-1]
|
||||
B) MODE_INHERITABLETHREADLOCAL, raw SimpleAsyncTaskExecutor(virtual): authenticated as bob [VirtualThread[#26,vt-1]/runnable@ForkJoinPool-1-worker-2]
|
||||
C) DelegatingSecurityContextExecutor around SimpleAsyncTaskExecutor(virtual): authenticated as carol [VirtualThread[#27,vt-1]/runnable@ForkJoinPool-1-worker-1]
|
||||
SecurityContextHolderThreadLocalAccessor present: true
|
||||
D) ContextPropagatingTaskDecorator on SimpleAsyncTaskExecutor(virtual), no Delegating* wrapper: authenticated as dave [VirtualThread[#28,vt-1]/runnable@ForkJoinPool-1-worker-1]
|
||||
5
context-propagation/docs/output/demo3.txt
Normal file
5
context-propagation/docs/output/demo3.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
=== Demo 3: StructuredTaskScope.fork() + SecurityContext ===
|
||||
A) plain fork, MODE_THREADLOCAL: NO AUTHENTICATION (lost)
|
||||
B) plain fork, MODE_INHERITABLETHREADLOCAL: authenticated as frank
|
||||
C) manual capture/restore: authenticated as grace
|
||||
D) ContextSnapshot.wrap: authenticated as heidi
|
||||
9
context-propagation/docs/output/demo4.txt
Normal file
9
context-propagation/docs/output/demo4.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
=== Demo 4: Executor/ExecutorService/AsyncTaskExecutor wrapping on a pooled platform thread ===
|
||||
A) raw ThreadPoolExecutor, no wrapper: NO AUTHENTICATION (lost)
|
||||
B) DelegatingSecurityContextExecutorService.execute(...): authenticated as bob
|
||||
B2) DelegatingSecurityContextExecutorService.submit(Callable): authenticated as bob
|
||||
EDGE) task 1 on possibly-reused worker: authenticated as carol-task1
|
||||
EDGE) task 2, same pool, different caller context: authenticated as dave-task2 <-- correct, NOT stale, unlike plain InheritableThreadLocal on a reused worker
|
||||
C) DelegatingSecurityContextExecutor + CompletableFuture.supplyAsync: authenticated as erin
|
||||
C2) default CompletableFuture executor (common ForkJoinPool), no wrapper: NO AUTHENTICATION (lost)
|
||||
D) DelegatingSecurityContextAsyncTaskExecutor wrapping ThreadPoolTaskExecutor: authenticated as grace
|
||||
6
context-propagation/docs/output/demo5.txt
Normal file
6
context-propagation/docs/output/demo5.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
=== Demo 5: ReactiveSecurityContextHolder vs. ThreadLocal across a scheduler hop ===
|
||||
A) SecurityContextHolder (ThreadLocal), no scheduler hop: authenticated as alice
|
||||
B) SecurityContextHolder (ThreadLocal), AFTER publishOn to a different thread: NO AUTHENTICATION (lost) [proves ThreadLocal doesn't survive a scheduler hop]
|
||||
C) ReactiveSecurityContextHolder + contextWrite, no scheduler hop: Hello, carol
|
||||
D) ReactiveSecurityContextHolder + contextWrite, AFTER publishOn to a different thread: Hello, dave [Context travels with the stream, not the thread]
|
||||
E) getProfile() with no contextWrite() upstream at all: Anonymous [defaultIfEmpty fires; getContext() completes empty, it does not error]
|
||||
6
context-propagation/docs/output/demo6.txt
Normal file
6
context-propagation/docs/output/demo6.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
=== Demo 6: DelegatingSecurityContextTaskScheduler and the synthetic system identity ===
|
||||
A) schedule() called with NO context present on the caller thread: NO AUTHENTICATION (lost) [this is the realistic startup case the post warns about]
|
||||
B1) first schedule() call, caller context = registration-thread-X: authenticated as registration-thread-X
|
||||
B2) second schedule() call on the SAME wrapper, caller context changed to registration-thread-Y: authenticated as registration-thread-Y [independent per-call capture, not frozen at wrapper construction]
|
||||
C) task body sets its own systemContext(), ignoring anything the scheduler wrapper captured: SYSTEM with authorities [ROLE_SYSTEM]
|
||||
EDGE) AuthenticationTrustResolver.isAnonymous(systemContext()): false [false -- SYSTEM is a normal authenticated principal, not Spring Security's anonymous concept]
|
||||
6
context-propagation/docs/output/demo7.txt
Normal file
6
context-propagation/docs/output/demo7.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
=== Demo 7: SecurityContextHolderFilter vs SecurityContextPersistenceFilter -- load vs. load+save ===
|
||||
A) SecurityContextPersistenceFilter, context set mid-chain, auto-saved to session after chain returns: true [true -- this filter saves for you]
|
||||
B) SecurityContextHolderFilter, context set mid-chain, auto-saved to session after chain returns: false [false -- requireExplicitSave's default; nothing persists unless you save it yourself]
|
||||
C) SecurityContextHolderFilter + explicit repository.saveContext(...) inside the chain: true [true -- the workaround the post recommends actually works]
|
||||
D) SecurityContextHolderFilter, context already saved in an existing session, next request: authenticated as dave [it does load -- "only loads, never saves" describes the SAVE side, not the LOAD side]
|
||||
EDGE) brand-new request, no prior session, nothing set: NO AUTHENTICATION (empty context, not an error)
|
||||
6
context-propagation/docs/output/tests.txt
Normal file
6
context-propagation/docs/output/tests.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
mvn test -- SecurityContextPropagationContractTest (10 tests pinning the claims each demo prints above)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Test set: com.ankurm.vt.SecurityContextPropagationContractTest
|
||||
-------------------------------------------------------------------------------
|
||||
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.413 s -- in com.ankurm.vt.SecurityContextPropagationContractTest
|
||||
Reference in New Issue
Block a user