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:
95
method-security/README.md
Normal file
95
method-security/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# method-security
|
||||
|
||||
Companion module for [Method Security in Spring Security 7: `@PreAuthorize`, `@PostAuthorize`
|
||||
and the Proxy Traps](https://ankurm.com/spring-security-7-method-security-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](../README.md); the sibling module is
|
||||
[context-propagation](../context-propagation/README.md).
|
||||
|
||||
## 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
|
||||
|
||||
```bash
|
||||
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](docs/01-how-method-security-runs.md) |
|
||||
| `Demo2SelfInvocation` | Why does an annotated method called from inside its own class run unchecked, and what are the three fixes? | [docs/03](docs/03-self-invocation.md) |
|
||||
| `Demo3NonProxyable` | Which of `final` / `static` / `private` / package-private / final-class / interface-only actually get advised? | [docs/04](docs/04-non-proxyable-methods.md) |
|
||||
| `Demo4SpelReference` | Every expression you can write inside the annotation, evaluated as two different users | [docs/02](docs/02-spel-reference.md) |
|
||||
| `Demo5FilteringTraps` | Which container types can `@PreFilter` / `@PostFilter` handle, and what happens on an immutable one? | [docs/05](docs/05-filtering.md) |
|
||||
| `Demo6InterceptorOrder` | Where does the security advice sit relative to `@Transactional`, and does a denial roll back? | [docs/07](docs/07-ordering-and-transactions.md) |
|
||||
| `Demo7DeniedHandling` | What is actually thrown, and how do `@HandleAuthorizationDenied` and `@AuthorizeReturnObject` change it? | [docs/06](docs/06-denied-handling.md) |
|
||||
| `Demo8MetaAnnotations` | Do `{value}` templates need a bean? What does a method-level rule do to a class-level one? | [docs/08](docs/08-meta-annotations.md) |
|
||||
| `Demo9ParameterNames` | The same class compiled with and without `-parameters` | [docs/02](docs/02-spel-reference.md) |
|
||||
| `MethodSecurityTrapsTest` | 14 assertions pinning every claim above | [docs/09](docs/09-audit-checklist.md) |
|
||||
|
||||
## Captured output
|
||||
|
||||
| File | From |
|
||||
|---|---|
|
||||
| [`docs/output/demo1.txt`](docs/output/demo1.txt) … [`demo8.txt`](docs/output/demo8.txt) | the eight demos above |
|
||||
| [`docs/output/demo9-with-parameters.txt`](docs/output/demo9-with-parameters.txt) | Demo 9, compiled with `-parameters` |
|
||||
| [`docs/output/demo9-without-parameters.txt`](docs/output/demo9-without-parameters.txt) | Demo 9, same source, compiled without it |
|
||||
| [`docs/output/tests.txt`](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](docs/09-audit-checklist.md) for the full index.
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [LICENSE](../LICENSE).
|
||||
Reference in New Issue
Block a user