1
0
Files
spring-security-demo/method-security
asmhatre 73ab67b171 Add the filter-chain module
Companion project for "The Spring Security Filter Chain Explained". A real
Spring Boot 4.1.1 servlet application whose scenarios are Spring profiles, plus
a diagnostic controller that prints the live FilterChainProxy, the reflected
FilterOrderRegistration table, and the servlet container's own registrations.

Twelve captured transcripts under docs/output/, nine cross-linked doc chapters,
21 assertions.

Also fixes a broken relative link in method-security/docs/01: the cross-module
reference to context-propagation/README.md needed two levels up, not one.
2026-08-26 02:21:47 +00:00
..
2026-08-26 02:21:47 +00:00

method-security

Companion module for Method Security in Spring Security 7: @PreAuthorize, @PostAuthorize and the Proxy Traps on ankurm.com.

Nine small programs and a JUnit suite, each answering one question about what @PreAuthorize and its siblings actually do at runtime — including the three cases where they do nothing at all and say nothing about it. No web layer, no Boot application, no server: a plain AnnotationConfigApplicationContext, a SecurityContextHolder, and real proxied beans, so every result is about method security and not about a filter chain.

Part of spring-security-demo; the sibling module is context-propagation.

Verified versions

Component Version
JDK 25 (Temurin 25.0.4.1+1), LTS
Spring Boot (reference target) 4.1.1
Spring Framework 7.0.9
Spring Security 7.1.1 (-core, -config, -test)
AspectJ Weaver 1.9.25 (only for exposeProxy in Demo 2)
Spring Data Commons 4.1.1 (only so Demo 5 can filter a real Page)
H2 2.4.240 (Demo 6's transaction rollback proof)
JUnit Jupiter 6.0.3
AssertJ 3.27.7

Latest GA on Maven Central at the time of writing, taken from maven-metadata.xml. 4.2.0-M1 / 7.2.0-M1 exist as milestones only.

Quickstart

mvn dependency:build-classpath -Dmdep.outputFile=cp.txt
javac --release 25 -parameters -cp "$(cat cp.txt)" -d target/classes $(find src/main -name '*.java')
java -cp "target/classes:$(cat cp.txt)" com.ankurm.methodsec.Demo2SelfInvocation

-parameters matters: without it every #parameterName expression in this module silently stops working, which is what Demo 9 is about.

Everything at once, regenerating docs/output/: scripts/run-all.sh. Just the assertions: mvn test.

What each demo shows

Demo Question Chapter
Demo1AnnotationsInAction What do all six annotation families do on the happy path, and what is thrown when they deny? docs/01
Demo2SelfInvocation Why does an annotated method called from inside its own class run unchecked, and what are the three fixes? docs/03
Demo3NonProxyable Which of final / static / private / package-private / final-class / interface-only actually get advised? docs/04
Demo4SpelReference Every expression you can write inside the annotation, evaluated as two different users docs/02
Demo5FilteringTraps Which container types can @PreFilter / @PostFilter handle, and what happens on an immutable one? docs/05
Demo6InterceptorOrder Where does the security advice sit relative to @Transactional, and does a denial roll back? docs/07
Demo7DeniedHandling What is actually thrown, and how do @HandleAuthorizationDenied and @AuthorizeReturnObject change it? docs/06
Demo8MetaAnnotations Do {value} templates need a bean? What does a method-level rule do to a class-level one? docs/08
Demo9ParameterNames The same class compiled with and without -parameters docs/02
MethodSecurityTrapsTest 14 assertions pinning every claim above docs/09

Captured output

File From
docs/output/demo1.txtdemo8.txt the eight demos above
docs/output/demo9-with-parameters.txt Demo 9, compiled with -parameters
docs/output/demo9-without-parameters.txt Demo 9, same source, compiled without it
docs/output/tests.txt mvn test

Regenerate all of it with scripts/run-all.sh. Nothing in docs/ or in the article is hand-typed output.

Documentation corrections found while building this

Each of these disagrees with the current reference documentation or with widely repeated guidance, and each was verified by running the code or reading the 7.1.1 source:

  • @EnableMethodSecurity has an offset attribute, not order.
  • AuthorizationProxyFactory is in org.springframework.security.authorization, not …authorization.method.
  • AbstractSecurityExpressionHandler.setRoleHierarchy(..) is deprecated in 7.1; AuthorizationManagerFactory is where role hierarchy and role prefix now live.
  • {value} meta-annotation templates work without an AnnotationTemplateExpressionDefaults bean.
  • Conflicting @PreAuthorize inherited from two interfaces fails at call time, not at startup.
  • @PreFilter on an immutable collection is a silent no-op, not an exception.
  • Package-private methods are advised by a CGLIB proxy.

See docs/09 for the full index.

License

MIT — see LICENSE.