Skip to content

Commit 122346b

Browse files
committed
Document AuthorizationManager for Method Security
Issue gh-9289
1 parent 6bcf479 commit 122346b

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

docs/manual/src/docs/asciidoc/_includes/servlet/authorization/method-security.adoc

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,169 @@ It provides support for JSR-250 annotation security as well as the framework's o
66
From 3.0 you can also make use of new <<el-access,expression-based annotations>>.
77
You can apply security to a single bean, using the `intercept-methods` element to decorate the bean declaration, or you can secure multiple beans across the entire service layer using the AspectJ style pointcuts.
88

9+
=== EnableMethodSecurity
10+
11+
In 5.5, we can enable annotation-based security using the `@EnableMethodSecurity` annotation on any `@Configuration` instance.
12+
13+
[NOTE]
14+
For earlier versions, please read about similar support with <<jc-enable-global-method-security, @EnableGlobalMethodSecurity>>.
15+
16+
For example, the following would enable Spring Security's `@PreAuthorize` annotation:
17+
18+
[source,java]
19+
----
20+
@EnableMethodSecurity
21+
public class MethodSecurityConfig {
22+
// ...
23+
}
24+
----
25+
26+
Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly.
27+
Spring Security's native annotatino support defines a set of attributes for the method.
28+
These will be passed to the `AuthorizationMethodInterceptor` for it to make the actual decision:
29+
30+
[source,java]
31+
----
32+
public interface BankService {
33+
34+
@PreAuthorize("hasRole('USER')")
35+
Account readAccount(Long id);
36+
37+
@PreAuthorize("hasRole('USER')")
38+
Account[] findAccounts();
39+
40+
@PreAuthorize("hasRole('TELLER')")
41+
Account post(Account account, double amount);
42+
}
43+
----
44+
45+
You can enable support for Spring Security's `@Secured` annotation using:
46+
47+
[source,java]
48+
----
49+
@EnableMethodSecurity(secureEnabled = true)
50+
public class MethodSecurityConfig {
51+
// ...
52+
}
53+
----
54+
55+
or JSR-250 using:
56+
57+
[source,java]
58+
----
59+
@EnableMethodSecurity(jsr250Enabled = true)
60+
public class MethodSecurityConfig {
61+
// ...
62+
}
63+
----
64+
65+
==== Customizing Authorization
66+
67+
Spring Security's `@PreAuthorize`, `@PostAuthorize`, `@PreFilter`, and `@PostFilter` ship with rich expression-based support.
68+
69+
If you need to customize the way that expressions are handled, you can expose a custom `MethodSecurityExpressionHandler`, like so:
70+
71+
[source,java]
72+
----
73+
@Bean
74+
MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
75+
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
76+
handler.setTrustResolver(myCustomTrustResolver);
77+
return handler;
78+
}
79+
----
80+
81+
Also, for role-based authorization, Spring Security adds a default `ROLE_` prefix, which is uses when evaluating expressions like `hasRole`.
82+
83+
You can configure the authorization rules to use a different prefix by exposing a `GrantedAuthorityDefaults` bean, like so:
84+
85+
[source,java]
86+
----
87+
@Bean
88+
GrantedAuthorityDefaults grantedAuthorityDefaults() {
89+
return new GrantedAuthorityDefaults("MYPREFIX_");
90+
}
91+
----
92+
93+
==== Custom Authorization Managers
94+
95+
Method authorization is a combination of before- and after-method authorization.
96+
97+
[NOTE]
98+
Before-method authorization is performed before the method is invoked.
99+
If that authorization denies access, the method is not invoked and an `AccessDeniedException` is thrown
100+
After-method authorization is performed after the method is invoked, but before the method returns to the caller.
101+
If that authorization denies access, the value is not returned and an `AccessDeniedException` is thrown
102+
103+
You can customize before-method authorization by publishing your own `AuthorizationMethodBeforeAdvice` bean, which includes your custom authorization manager as well as the `Pointcut` that describes when your manager should be used.
104+
105+
For example, you may want to apply a default authorization rule to all methods in your service layer.
106+
To do this, you'll supply the pointcut as well as the rule, like so:
107+
108+
[source,java]
109+
----
110+
@Bean
111+
public AuthorizationMethodBeforeAdvice<MethodAuthorizationContext> authorizationMethodBeforeAdvice() {
112+
JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut();
113+
pattern.setPattern("org.mycompany.myapp.service.*");
114+
AuthorizationManager<MethodAuthorizationContext> rule = AuthorityAuthorizationManager.isAuthenticated();
115+
return new AuthorizationManagerMethodBeforeAdvice(pattern, rule);
116+
}
117+
----
118+
119+
This will replace any default before advice that Spring Security provides.
120+
To use your custom rule as well as Spring Security's `@PreAuthorize` authorization support, you can do:
121+
122+
[source,java]
123+
----
124+
@Bean
125+
public AuthorizationMethodBeforeAdvice<MethodAuthorizationContext> authorizationMethodBeforeAdvice() {
126+
JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut();
127+
pattern.setPattern("org.mycompany.myapp.service.*");
128+
AuthorizationManager rule = AuthorityAuthorizationManager.isAuthenticated();
129+
AuthorizationMethodBeforeAdvice custom = new AuthorizationManagerMethodBeforeAdvice(pattern, rule);
130+
AuthorizationMethodBeforeAdvice pre = new AuthorizationMethodBeforeAdvice(
131+
AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class),
132+
new PreAuthorizeAuthorizationManager());
133+
return new DelegatingAuthorizationManagerBeforeAdvice(custom, pre);
134+
}
135+
----
136+
137+
The same can be done for after-method authorization.
138+
After-method authorization is generally concerned with analysing the return value to verify access.
139+
140+
For example, you might have a method that confirms that the account requested actually belongs to the logged-in user like so:
141+
142+
[source,java]
143+
----
144+
public interface BankService {
145+
146+
@PreAuthorize("hasRole('USER')")
147+
@PostAuthorize("returnObject.owner == authentication.name")
148+
Account readAccount(Long id);
149+
}
150+
----
151+
152+
You can supply your own `AuthorizationMethodAfterAdvice` to customize how access to the return value is evaluated.
153+
154+
For example, you can give special access to a given role in your system, like so:
155+
156+
[source,java]
157+
----
158+
@Bean
159+
public AuthorizationMethodAfterAdvice<MethodAuthorizationContext> authorizationMethodAfterAdvice() {
160+
JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut();
161+
pattern.setPattern("org.mycompany.myapp.service.*");
162+
AuthorizationManager<MethodAuthorizationContext> rule = AuthorityAuthorizationManager.hasRole("TELLER");
163+
AuthorizationMethodBeforeAdvice custom = new AuthorizationManagerMethodBeforeAdvice(pattern, rule);
164+
AuthorizationMethodBeforeAdvice post = new AuthorizationManagerMethodBeforeAdvice(
165+
AuthorizationMethodPointcuts.forAnnotations(PostAuthorize.class),
166+
new PostAuthorizeAuthorizationManager());
167+
return new DelegatingAuthorizationManagerBeforeAdvice(custom, post);
168+
}
169+
----
170+
171+
[[jc-enable-global-method-security]]
9172
=== EnableGlobalMethodSecurity
10173

11174
We can enable annotation-based security using the `@EnableGlobalMethodSecurity` annotation on any `@Configuration` instance.

0 commit comments

Comments
 (0)