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
59 lines
2.8 KiB
Plaintext
59 lines
2.8 KiB
Plaintext
==============================================================================
|
|
Demo 6 -- interceptor order, and @PostAuthorize vs @Transactional
|
|
==============================================================================
|
|
|
|
AuthorizationInterceptorsOrder, read from the enum itself
|
|
---------------------------------------------------------
|
|
CONSTANT getOrder()
|
|
FIRST -2147483648
|
|
PRE_FILTER 100
|
|
PRE_AUTHORIZE 200
|
|
SECURED 300
|
|
JSR250 400
|
|
SECURE_RESULT 450
|
|
POST_AUTHORIZE 500
|
|
POST_FILTER 600
|
|
LAST 2147483647
|
|
|
|
Lower order = higher precedence = further OUT in the chain. Spring's own
|
|
@Transactional advisor defaults to Ordered.LOWEST_PRECEDENCE (2147483647),
|
|
which is larger than every number above -- so security wraps transactions,
|
|
not the other way round.
|
|
SLF4J(W): No SLF4J providers were found.
|
|
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
|
|
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
|
|
|
|
The advisor chain on a bean carrying all four annotations
|
|
---------------------------------------------------------
|
|
advisors applied to the proxy: 4
|
|
ORDER ADVISOR BEAN (as registered by @EnableMethodSecurity)
|
|
100 preFilterAuthorizationMethodInterceptor
|
|
200 preAuthorizeAuthorizationMethodInterceptor
|
|
450 authorizeReturnObjectMethodInterceptor
|
|
500 postAuthorizeAuthorizationMethodInterceptor
|
|
600 postFilterAuthorizationMethodInterceptor
|
|
(authorizeReturnObject sits at SECURE_RESULT = 450 and is registered
|
|
whether or not anything in the app uses @AuthorizeReturnObject.)
|
|
|
|
For BEFORE advice, a lower order runs earlier: @PreFilter (100) really
|
|
does run before @PreAuthorize (200). For AFTER advice the same numbers
|
|
mean the opposite. @PostAuthorize (500) sits FURTHER OUT than
|
|
@PostFilter (600), so on the way back out @PostFilter finishes first
|
|
and @PostAuthorize evaluates returnObject on the ALREADY-FILTERED list.
|
|
|
|
Both methods below return the same 3 elements and filter one away:
|
|
@PostAuthorize returnObject.size() == 3 DENIED -> AuthorizationDeniedException: Access Denied
|
|
@PostAuthorize returnObject.size() == 2 ALLOWED -> [a, b]
|
|
|
|
Default order: @PostAuthorize denies AFTER the transaction commits
|
|
------------------------------------------------------------------
|
|
rows before : 0
|
|
recordAndReturn("bob") @PostAuthorize DENIED -> AuthorizationDeniedException: Access Denied
|
|
rows after the denial : 1
|
|
|
|
@EnableTransactionManagement(order = FIRST): the write rolls back
|
|
-----------------------------------------------------------------
|
|
rows before : 0
|
|
recordAndReturn("bob") @PostAuthorize DENIED -> AuthorizationDeniedException: Access Denied
|
|
rows after the denial : 0
|