-
Notifications
You must be signed in to change notification settings - Fork 6.2k
AuthorizationManager + Method Security Support #9350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
jzheaux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @evgeniycheban! This is a good start.
I've left some feedback inline. In addition to that, please keep classes final until there is a clear need for extension.
I have some additional thoughts, but I'm guessing they will shake out when you add Pre/PostAuthorize support.
...ork/security/access/intercept/aopalliance/MethodSecurityAuthorizationManagerInterceptor.java
Outdated
Show resolved
Hide resolved
...ngframework/security/config/annotation/method/configuration/MethodSecurityConfiguration.java
Outdated
Show resolved
Hide resolved
2f7ca1f to
a2ae4a6
Compare
|
@jzheaux I added support for |
a2ae4a6 to
05a35ee
Compare
jzheaux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @evgeniycheban! I've left some additional feedback.
...ccess/expression/method/ExpressionBasedPostMethodInvocationAuthorizationManagerResolver.java
Outdated
Show resolved
Hide resolved
...ccess/expression/method/ExpressionBasedPostMethodInvocationAuthorizationManagerResolver.java
Outdated
Show resolved
Hide resolved
...rg/springframework/security/access/intercept/aopalliance/AuthorizationMethodInterceptor.java
Outdated
Show resolved
Hide resolved
...ccess/expression/method/ExpressionBasedPostMethodInvocationAuthorizationManagerResolver.java
Outdated
Show resolved
Hide resolved
fb11b02 to
d0244a5
Compare
jzheaux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @evgeniycheban! I've left my feedback inline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this interface, though I wonder if a better name is AuthorizationManagerAfterAdvice. The reason for that is that it's clear from the name that it is intercepting and perhaps mutating the return value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to AuthorizationManagerAfterAdvice.
...org/springframework/security/access/method/MethodInvocationAuthorizationManagerResolver.java
Outdated
Show resolved
Hide resolved
d50798a to
3822746
Compare
jzheaux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, @evgeniycheban! It's really starting to take shape. I've left some feedback inline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could instead do:
this.pointcut = Pointcuts.union(this.beforeAdvice, this.afterAdvice);Then, you can remove the inner class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know Spring Security did a lot of this in the past, but I'd like to see if this can be changed to be bean-based instead of based on extending a class.
One way that might work would be to do:
@Autowired(required = false)
public void setMethodSecurityExpressionHandler(MethodSecurityExpressionHandler custom) {
this.methodSecurityExpressionHandler = custom;
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If successful, then let's also make the class final
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The @Configuration class cannot be final because Spring creates a CGLIB proxy for it. I think we could make it just package private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, setting the proxyBeanMethods attribute to false allows the @Configuration class to be final.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might not go into this PR, but it would be nice if an application could do:
@Bean
public AuthorizationManagerBeforeAdvice<MethodInvocation> myBeforeAdvice() {
// ....
}
@Bean
public AuthorizationManagerAfterAdvice<MethodInvocation> myAfterAdvice() {
// ...
}And MethodSecurityConfiguration would take that one instead of its own.
This would be the equivalent of supplying a custom SecurityMetadataSource
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the class is expression-based, it would be ambiguous if other expression-based ways to give advice were added later on to the framework. We might want to call this PreAnnotationAuthorizationManagerAfterAdvice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should match the AffirmativeBased matcher, since that's the default in @EnableGlobalMethodSecurity. It returns the first voter that grants and only denies if one of the voters denied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. In the current version the DelegatingAuthorizationManagerBeforeAdvice returns the first granted AuthorizationDecision and the denied AuthorizationDecision only if one of the DelegatingAuthorizationManagerBeforeAdvices denied. If multiple DelegatingAuthorizationManagerBeforeAdvices denies then the first denied AuthorizationDecision is returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend that this change to a setter. Typically, Spring Security places required parameters in the constructor and optional ones as setters. Since there's a default handler that will work in most cases, using the default constructor will make it more convenient for applications to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
3822746 to
abc9965
Compare
26a3ab8 to
cb62099
Compare
cb62099 to
af92fd5
Compare
|
@jzheaux I've updated the PR according to your comments. |
a5b27e9 to
2b7e042
Compare
jzheaux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your patience, @evgeniycheban, while I got back to you.
I've left some additional feedback inline.
| * @param beforeAdvice the {@link AuthorizationManagerBeforeAdvice} to use | ||
| * @param afterAdvice the {@link AuthorizationManagerAfterAdvice} to use | ||
| */ | ||
| public AuthorizationMethodInterceptor(AuthorizationManagerBeforeAdvice<MethodInvocation> beforeAdvice, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rwinch made a good point that it would be nice to see if we can change AuthorizationManagerBeforeAdvice so that it doesn't extend AuthorizationManager.
Two ideas come to mind:
- Change this constructor to
public AuthorizationMethodInterceptor(AuthorizationManagerBeforeAdvice<MethodInvocation> beforeAdvice,
AuthorizationManager<MethodInvocation> beforeManager,
AuthorizationManagerAfterAdvice<MethodInvocation> afterAdvice,
AuthorizationManager<MethodInvocation> afterManager)and then PreAnnotationAuthorizationManagerBeforeAdvice would split into two classes --PreFilterAuthorizationManagerBeforeAdvice and PreAuthorizeAuthorizationManager -- and likewise for PostAnnotationXXX
2. Keep the contract as-is, but split PreAnnotationAuthorizationManagerBeforeAdvice into PreFilterAuthorizationManagerBeforeAdvice and something like MethodMatcherAuthorizationManagerBeforeAdvice. The latter would could have an instance of AuthorizationManager (e.g. PreAuthorizeAuthorizationManager) that it would delegate to if the MethodMatcher matches.
The second seems ideal, but I'm listing both for completeness.
In both cases, it seems like the before advice contract would change to return void since not all advices would return an AuthorizationDecision anymore.
1029660 to
60294fe
Compare
806d203 to
1689a72
Compare
jzheaux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, @evgeniycheban!
I've left some additional feedback inline.
Also, we're probably close enough to add @since 5.5 to new classes.
...rg/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this class is no longer needed. DefaultPointcutAdvisor should suffice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
...ngframework/security/config/annotation/method/configuration/MethodSecurityConfiguration.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's please move all these classes to org.springframework.security.authorization.method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking it would be better to have this use MethodAuthorizationContext instead of MethodInvocation. That way, only one MethodAuthorizationContext needs to be generated in AuthorizationMethodInterceptor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
@jzheaux I updated the PR with the JSR-250 security annotations support. |
|
Thanks again for all the hard work on this PR, @evgeniycheban, it's much appreciated! It's been merged in 20778f7. I also added some polish commits relative to documentation and some small bug fixes. Finally, since we are close to release time, I polished the AOP structure, changing the advice classes to interceptors. These match very nicely with the surrounding interceptor and remove a number of classes needed to support the previous structure. |
Closes gh-9289