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
89 lines
3.4 KiB
Java
89 lines
3.4 KiB
Java
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";
|
|
}
|
|
|
|
}
|
|
|
|
}
|