1
0
Files
spring-security-demo/README.md
2026-08-29 09:31:09 +05:30

5.6 KiB

spring-security-demo

Companion code for the Spring Security series on ankurm.com. Each directory is a self-contained Maven project for one article, with its own pom.xml, its own numbered documentation chapters, and its own captured output under docs/output/ — regenerated by that module's scripts/run-all.sh, never typed by hand.

Module Article What it demonstrates
context-propagation/ Spring Security Context Propagation: The Complete Guide Whether a SecurityContext survives @Async, executors, virtual threads, StructuredTaskScope, Reactor, schedulers and the servlet filter chain
method-security/ Method Security in Spring Security 7: @PreAuthorize, @PostAuthorize and the Proxy Traps What the method-security annotations do, the full SpEL surface, and the cases where the check silently does not run
filter-chain/ The Spring Security Filter Chain Explained Every filter in the default chain and its order number, where a custom filter actually lands, and how to read the TRACE log
cors-csrf/ CORS, CSRF and SameSite in Spring Boot 4 Why MVC-layer CORS does not fix a security-layer preflight rejection, what csrf.spa() assigns, and the cookie a browser silently refuses to store
service-to-service/ Securing Spring Boot Microservices: Token Relay, Service-to-Service JWT and mTLS Whose identity arrives at the last service under relay, client credentials and token exchange — and what a resource server does not check by default
ssrf/ HTTP Client SSRF Mitigation in Spring Boot 4.1 A working SSRF exploit against a link-preview endpoint, and the InetAddressFilter that stops it — including the two ways of configuring it that silently do the opposite

They are related more closely than they look. filter-chain is about how an Authentication gets into SecurityContextHolder in the first place and in what order; context-propagation is about whether it survives leaving the request thread; method-security reads it back on whatever thread it ends up on. An @Async method carrying @PreAuthorize fails with AuthenticationCredentialsNotFoundException for reasons that belong to the second module, not the third — and a custom authentication filter that never populated the context in the first place fails the same way, for reasons that belong to the first.

ssrf is the outbound counterpart to all of them. Every other module asks what a request arriving at this application is allowed to do; this one asks where this application is allowed to send a request, which turns out to be the question an attacker cares about once they have found an endpoint that fetches a URL. Its filter is not part of Spring Security at all — it is a Boot 4.1 HTTP-client control — and that is worth noticing, because a SecurityFilterChain has nothing to say about it.

service-to-service is the same question one process further out: cors-csrf and context-propagation ask whether an identity survives a thread or a browser boundary, and this one asks whether it survives an HTTP boundary — and what the service on the far side bothers to verify about it. Its /edge/relay-async endpoint fails for exactly the reason context-propagation documents.

cors-csrf is where those order numbers stop being trivia. CorsFilter at 1000 and CsrfFilter at 1100 both sit far above AuthorizationFilter at 4200, and almost every confusing symptom in that module is a consequence of one of those three positions — including a 403 that arrives as a 401 because the container re-dispatched the request to /error and the chain ran a second time.

Common ground

All modules target the same verified stack: JDK 25 (Temurin 25.0.4.1+1), Spring Framework 7.0.9, Spring Security 7.1.1 — the versions Spring Boot 4.1.1 manages. Versions were taken from maven-metadata.xml on Maven Central rather than from release announcements.

context-propagation additionally needs --enable-preview, because StructuredTaskScope is still a preview API on JDK 25. method-security does not. filter-chain, cors-csrf and service-to-service are real servlet applications: they inherit spring-boot-starter-parent and run on Tomcat, because the things they demonstrate only exist inside a servlet container. service-to-service runs five of them at once, and is the only module that also pulls in Spring Cloud — a separate release train, built against Boot 4.0.8 rather than 4.1.1.

Running a module

cd cors-csrf                # or context-propagation, method-security, filter-chain, service-to-service
./scripts/run-all.sh        # every demo plus the test suite, regenerating docs/output/
mvn test                    # just the assertions

filter-chain and cors-csrf also have ./scripts/run.sh <profile> and ./scripts/stop.sh, because their scenarios are a running web application rather than a main() method. cors-csrf adds ./scripts/preflight.sh, which sends one CORS preflight and prints the headers that decide the outcome.

License

MIT — see LICENSE.