SEC-2334: Expose createDefaultDecisionVoters method in UrlAuthorizationConfigurer, ExpressionUrlAuthorizationConfigurer, GlobalMethodSecurityConfiguration #2559
Labels
in: config
An issue in spring-security-config
status: declined
A suggestion or change that we don't feel we should currently apply
type: enhancement
A general enhancement
type: jira
An issue that was migrated from JIRA
Nick Williams (Migrated from SEC-2334) said:
Currently,
UrlAuthorizationConfigurer
,ExpressionUrlAuthorizationConfigurer
, andGlobalMethodSecurityConfiguration
provide ways for configuring a customAccessDecisionManager
(either by calling a method, as in the first two cases, or overriding a method, as in the latter case). For all of the standardAccessDecisionManager
implementations, you want to construct them with aList
ofAccessDecisionVoter
implementations. Then, someAccessDecisionVoter
implementations require either aSecurityExpressionHandler
orPreInvocationAuthorizationAdvice
to function properly.So, taking the
ExpressionUrlAuthorizationConfigurer
case as an example (theUrlAuthorizationConfigurer
case is extremely similar), let's take a look at what's involved to simply switch from theAffirmativeBased
decision manager to theConsensusBased
decision manager:The obvious problem here is that the first four lines of code in this method are duplicated and unnecessary. They are identical to code found in
ExpressionUrlAuthorizationConfigurer
. NowAbstractInterceptUrlConfigurer
defines a package-private, abstract methodgetDecisionVoters
thatUrlAuthorizationConfigurer
andExpressionUrlAuthorizationConfigurer
implement. How does this configuration method change if we makegetDecisionVoters
public and take advantage of it?This code is much cleaner and takes advantage of the default, standard expression handler and voters while using a different decision manager. For clarity, it might make sense to rename
getDecisionVoters
to something likecreateDefaultDecisionVoters
, but you get the idea.Next let's take a look at
GlobalMethodSecurityConfiguration
. Assume you want to do the same thing with it: just change from theAffirmativeBased
to theConsensusBased
decision manager. As of now:Once again, we've duplicated a lot of code unnecessarily. Additionally,
prePostEnabled()
andjsr250Enabled()
have private access and can't be called from here. Arguably you could eliminate this last problem by only adding the voters that your@EnableGlobalMethodSecurity
config requires, but still. It's definitely not clean, and the only way to get it "right" is to have some knowledge of the Spring Security source code. Now let's look at this same change using the (currently non-existent)createDefaultDecisionVoters
method:WOW. Much cleaner. Adding the
createDefaultDecisionVoters()
here also provides us with another capability. If you want, you can create the default voters and add just your one custom voter to them, still creating the default decision manager (or a custom decision manager--it's up to you):Finally, in both of these cases, exposing a
getDecisionVoters
/createDefaultDecisionVoters
method ensures that if any bug fixes are made to the default implementations, or if any new default voters are added, the user gets this update on the next upgrade.Given these use cases and compelling arguments :-), I propose the following:
Rename
AbstractInterceptUrlConfigurer#getDecisionVoters
tocreateDefaultDecisionVoters
and make it public.Create a
GlobalMethodSecurityConfiguration#getDecisionVoters
method, move the voter creation to it, and make it protected.It's possible I missed other configuration classes with similar design, in which case I implicitly make analogous proposals for those classes as well.
The text was updated successfully, but these errors were encountered: