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:
@@ -0,0 +1,88 @@
|
||||
package com.ankurm.methodsec;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.core.parameters.P;
|
||||
|
||||
/**
|
||||
* Demo 9 -- {@code #parameterName} depends on a compiler flag.
|
||||
*
|
||||
* <p>{@code @PreAuthorize("#owner == authentication.name")} resolves {@code #owner} by looking
|
||||
* up the method's parameter names through a {@code ParameterNameDiscoverer}. Parameter names
|
||||
* survive compilation only when {@code javac} is given {@code -parameters}. Without it the
|
||||
* name is {@code arg0}, {@code #owner} resolves to nothing, and the comparison is false --
|
||||
* every call is denied.
|
||||
*
|
||||
* <p>{@code scripts/run-all.sh} compiles this module twice and runs this class from both
|
||||
* builds, so {@code docs/output/demo9-with-parameters.txt} and
|
||||
* {@code docs/output/demo9-without-parameters.txt} are the same code under the two flags.
|
||||
*
|
||||
* <p>Chapter:
|
||||
* <a href="../../../../../../docs/02-spel-reference.md">docs/02-spel-reference.md</a>.
|
||||
*/
|
||||
public class Demo9ParameterNames {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Support.banner("Demo 9 -- #parameterName and the -parameters compiler flag");
|
||||
|
||||
Method byName = Owned.class.getMethod("byParameterName", String.class);
|
||||
Method byAlias = Owned.class.getMethod("byParameterAlias", String.class);
|
||||
System.out.println(" compiled with -parameters : " + byName.getParameters()[0].isNamePresent());
|
||||
System.out.println(" byParameterName param[0] : " + byName.getParameters()[0].getName());
|
||||
System.out.println(" byParameterAlias param[0] : " + byAlias.getParameters()[0].getName()
|
||||
+ " (annotated @P(\"o\"))");
|
||||
|
||||
try (var ctx = new AnnotationConfigApplicationContext(Config.class)) {
|
||||
Owned owned = ctx.getBean(Owned.class);
|
||||
Support.login("alice", "ROLE_USER");
|
||||
|
||||
Support.heading("alice calling with her own name");
|
||||
Support.attempt("#owner == authentication.name", () -> owned.byParameterName("alice"));
|
||||
Support.attempt("#o == authentication.name (@P(\"o\"))", () -> owned.byParameterAlias("alice"));
|
||||
|
||||
Support.heading("alice calling with somebody else's name");
|
||||
Support.attempt("#owner == authentication.name", () -> owned.byParameterName("bob"));
|
||||
Support.attempt("#o == authentication.name (@P(\"o\"))", () -> owned.byParameterAlias("bob"));
|
||||
}
|
||||
finally {
|
||||
Support.logout();
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println(" Without -parameters the first expression denies BOTH calls -- it fails");
|
||||
System.out.println(" closed, which is the good direction, but it fails silently in the sense");
|
||||
System.out.println(" that nothing tells you the rule is not the rule you wrote. @P(\"o\") does");
|
||||
System.out.println(" not depend on the flag, because the name is in the class file either way.");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
Owned owned() {
|
||||
return new Owned();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Owned {
|
||||
|
||||
@PreAuthorize("#owner == authentication.name")
|
||||
public String byParameterName(String owner) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@PreAuthorize("#o == authentication.name")
|
||||
public String byParameterAlias(@P("o") String owner) {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user