Add virtual-thread, structured-concurrency demos for the Spring Security context propagation guide
Three verified programs (JDK 25, Spring Security 7.1.1, Spring Boot 4.1.1 dependency versions) backing the ankurm.com post: InheritableThreadLocal across thread models, @Async on a virtual-thread SimpleAsyncTaskExecutor (DelegatingSecurityContextExecutor vs ContextPropagatingTaskDecorator), and StructuredTaskScope.fork() propagation. Captured console output and docs chapters included.
This commit is contained in:
59
README.md
Normal file
59
README.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# spring-security-demo
|
||||
|
||||
Companion repo for [Spring Security Context Propagation - Complete
|
||||
Guide](https://ankurm.com/spring-security-context-propagation-complete-guide/) on ankurm.com.
|
||||
Three small, dependency-light programs that answer one question each: does a Spring Security
|
||||
`SecurityContext` survive a specific thread hand-off? No web server, no HTTP -- every scenario
|
||||
sets an `Authentication` on the calling thread and checks whether the other side of the hand-off
|
||||
can see it.
|
||||
|
||||
## Verified versions
|
||||
|
||||
| Component | Version |
|
||||
|---|---|
|
||||
| JDK | 25 (Temurin 25.0.4.1+1), LTS, GA 2025-09-16 |
|
||||
| Spring Boot (reference target) | 4.1.1 |
|
||||
| Spring Framework | 7.0.9 |
|
||||
| Spring Security | 7.1.1 |
|
||||
| `io.micrometer:context-propagation` | 1.2.1 (as managed by Boot 4.1.1's BOM) |
|
||||
|
||||
`StructuredTaskScope` is a **preview API** on JDK 25 (JEP 505, fifth preview) and remains
|
||||
preview through JDK 26 (JEP 525, sixth preview) -- every build/run command below needs
|
||||
`--enable-preview`.
|
||||
|
||||
## Quickstart
|
||||
|
||||
```bash
|
||||
mvn dependency:build-classpath -Dmdep.outputFile=cp.txt
|
||||
javac --release 25 --enable-preview -cp "$(cat cp.txt)" -d target/classes $(find src -name '*.java')
|
||||
java --enable-preview -cp "target/classes:$(cat cp.txt)" com.ankurm.vt.Demo1PlainThreadLocal
|
||||
```
|
||||
|
||||
Or just run everything and regenerate the captured output: `scripts/run-all.sh`.
|
||||
|
||||
## What each demo shows
|
||||
|
||||
| Demo | Question | Chapter |
|
||||
|---|---|---|
|
||||
| `Demo1PlainThreadLocal` | Does `InheritableThreadLocal` behave differently for a pooled platform thread vs. a fresh virtual thread? (No Spring.) | [docs/01](docs/01-inheritable-threadlocal.md) |
|
||||
| `Demo2AsyncVirtualThreads` | Does the Boot-4.1-style virtual-thread `@Async` executor propagate `SecurityContext`, and what four fixes change? | [docs/02](docs/02-async-virtual-threads.md) |
|
||||
| `Demo3StructuredConcurrency` | Does a `StructuredTaskScope.fork()` subtask see the parent's `SecurityContext`? | [docs/03](docs/03-structured-concurrency.md) |
|
||||
|
||||
## Captured output
|
||||
|
||||
Every number and log line in the blog post traces back to one of these, produced by
|
||||
`scripts/run-all.sh`, not retyped:
|
||||
|
||||
- [docs/output/demo1.txt](docs/output/demo1.txt)
|
||||
- [docs/output/demo2.txt](docs/output/demo2.txt)
|
||||
- [docs/output/demo3.txt](docs/output/demo3.txt)
|
||||
|
||||
## The one-line summary of all three chapters
|
||||
|
||||
`SecurityContextHolder` is a `ThreadLocal`. Nothing about virtual threads or structured
|
||||
concurrency changes that. What changed is that virtual threads are never pooled, so
|
||||
`MODE_INHERITABLETHREADLOCAL`'s old danger (stale context on a reused pool worker) doesn't
|
||||
apply to them -- and Spring Security 6.5 gave `SecurityContextHolder` a Micrometer
|
||||
`ThreadLocalAccessor`, so `ContextPropagatingTaskDecorator` / `ContextSnapshot.wrap(...)` now
|
||||
propagate it automatically, alongside MDC and tracing context, without a
|
||||
`DelegatingSecurityContext*` wrapper.
|
||||
Reference in New Issue
Block a user