Revert AuthorizationManager Method Security
This commit is contained in:
@@ -6,185 +6,6 @@ It provides support for JSR-250 annotation security as well as the framework's o
|
||||
From 3.0 you can also make use of new <<el-access,expression-based annotations>>.
|
||||
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.
|
||||
|
||||
=== EnableMethodSecurity
|
||||
|
||||
In 5.5, we can enable annotation-based security using the `@EnableMethodSecurity` annotation on any `@Configuration` instance.
|
||||
|
||||
[NOTE]
|
||||
For earlier versions, please read about similar support with <<jc-enable-global-method-security, @EnableGlobalMethodSecurity>>.
|
||||
|
||||
For example, the following would enable Spring Security's `@PreAuthorize` annotation:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableMethodSecurity
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly.
|
||||
Spring Security's native annotatino support defines a set of attributes for the method.
|
||||
These will be passed to the `DefaultAuthorizationMethodInterceptorChain` for it to make the actual decision:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@PreAuthorize("hasRole('USER')")
|
||||
Account readAccount(Long id);
|
||||
|
||||
@PreAuthorize("hasRole('USER')")
|
||||
Account[] findAccounts();
|
||||
|
||||
@PreAuthorize("hasRole('TELLER')")
|
||||
Account post(Account account, double amount);
|
||||
}
|
||||
----
|
||||
|
||||
You can enable support for Spring Security's `@Secured` annotation using:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableMethodSecurity(secureEnabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
or JSR-250 using:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableMethodSecurity(jsr250Enabled = true)
|
||||
public class MethodSecurityConfig {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
==== Customizing Authorization
|
||||
|
||||
Spring Security's `@PreAuthorize`, `@PostAuthorize`, `@PreFilter`, and `@PostFilter` ship with rich expression-based support.
|
||||
|
||||
If you need to customize the way that expressions are handled, you can expose a custom `MethodSecurityExpressionHandler`, like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
|
||||
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
|
||||
handler.setTrustResolver(myCustomTrustResolver);
|
||||
return handler;
|
||||
}
|
||||
----
|
||||
|
||||
Also, for role-based authorization, Spring Security adds a default `ROLE_` prefix, which is uses when evaluating expressions like `hasRole`.
|
||||
|
||||
You can configure the authorization rules to use a different prefix by exposing a `GrantedAuthorityDefaults` bean, like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults() {
|
||||
return new GrantedAuthorityDefaults("MYPREFIX_");
|
||||
}
|
||||
----
|
||||
|
||||
==== Custom Authorization Managers
|
||||
|
||||
Method authorization is a combination of before- and after-method authorization.
|
||||
|
||||
[NOTE]
|
||||
Before-method authorization is performed before the method is invoked.
|
||||
If that authorization denies access, the method is not invoked and an `AccessDeniedException` is thrown
|
||||
After-method authorization is performed after the method is invoked, but before the method returns to the caller.
|
||||
If that authorization denies access, the value is not returned and an `AccessDeniedException` is thrown
|
||||
|
||||
To recreate what Spring Security does by default, you would publish the following bean:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public List<AuthorizationMethodInterceptor> methodSecurity() {
|
||||
return new DelegatingAuthorizationMethodInterceptor(
|
||||
new PreFilterAuthorizationMethodInterceptor(), // before-method
|
||||
AuthorizationMethodInterceptors.preAuthorize(), // before-method
|
||||
new PostFilterAuthorizationMethodInterceptor(), // after-method
|
||||
AuthorizationMethodInterceptors.postAuthorize() // after-method
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
Keep in mind that publishing a list of `AuthorizationMethodInterceptor`s will completely replace any Spring Security defaults.
|
||||
|
||||
Interceptors are invoked in the order that they are declared.
|
||||
|
||||
You may want to only support `@PreAuthorize` in your application, in which case you can do the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public AuthorizationMethodInterceptor methodSecurity() {
|
||||
return AuthorizationMethodInterceptors.preAuthorize();
|
||||
}
|
||||
----
|
||||
|
||||
Or, you may have a custom before-method `AuthorizationManager` that you want to add to the list.
|
||||
|
||||
In this case, you will need to tell Spring Security both the `AuthorizationManager` and to which methods and classes your authorization manager applies.
|
||||
|
||||
Spring Security integrates with Spring AOP to achieve this.
|
||||
Thus, you can configure Spring Security to support `@PreAuthorize`, `@PostAuthorize`, and your own `AuthorizationManager` like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public AuthorizationMethodInterceptor methodSecurity() {
|
||||
JdkRegexpMethodPointcut pattern = new JdkRegexpMethodPointcut();
|
||||
pattern.setPattern("org.mycompany.myapp.service.*");
|
||||
AuthorizationManager<MethodInvocation> rule = AuthorityAuthorizationManager.isAuthenticated();
|
||||
return new DelegatingAuthorizationMethodInterceptor(
|
||||
AuthorizationMethodInterceptors.preAuthorize(),
|
||||
new AuthorizationManagerBeforeMethodInterceptor(pattern, rule),
|
||||
AuthorizationMethodInterceptors.postAuthorize()
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
The same can be done for after-method authorization and `AfterMethodAuthorizationManager`.
|
||||
After-method authorization is generally concerned with analysing the return value to verify access.
|
||||
|
||||
For example, you might have a method that confirms that the account requested actually belongs to the logged-in user like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface BankService {
|
||||
|
||||
@PreAuthorize("hasRole('USER')")
|
||||
@PostAuthorize("returnObject.owner == authentication.name")
|
||||
Account readAccount(Long id);
|
||||
}
|
||||
----
|
||||
|
||||
You can supply your own `AuthorizationMethodInterceptor` to customize how access to the return value is evaluated.
|
||||
|
||||
For example, instead of embedding a great deal of logic into the `@PostAuthorize` SpEL expression, you may want to wire your own `@Bean`.
|
||||
In that case, you can configure it like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public AuthorizationMethodInterceptor methodSecurity
|
||||
(AfterMethodAuthorizationManager<MethodInvocation> rules) {
|
||||
AnnotationMethodMatcher pattern = new AnnotationMethodMatcher(MySecurityAnnotation.class);
|
||||
return new DelegatingAuthorizationMethodInterceptor(
|
||||
AuthorizationMethodInterceptors.preAuthorize(),
|
||||
new AuthorizationManagerAfterMethodInterceptor(pattern, rules));
|
||||
}
|
||||
----
|
||||
|
||||
[[jc-enable-global-method-security]]
|
||||
=== EnableGlobalMethodSecurity
|
||||
|
||||
We can enable annotation-based security using the `@EnableGlobalMethodSecurity` annotation on any `@Configuration` instance.
|
||||
|
||||
Reference in New Issue
Block a user