-
Notifications
You must be signed in to change notification settings - Fork 188
refactor: Obtain SecurityContext from the SecurityContextHolderStrategy bean #21665
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
95f2ac4 to
06f63c2
Compare
|
| * @param evaluator | ||
| * evaluator to check path permissions. | ||
| * @deprecated Use | ||
| * {@link #SpringAccessPathChecker(WebInvocationPrivilegeEvaluator, String)} |
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.
| * {@link #SpringAccessPathChecker(WebInvocationPrivilegeEvaluator, String)} | |
| * {@link #SpringAccessPathChecker(SecurityContextHolderStrategy, WebInvocationPrivilegeEvaluator)} |
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 would be good to add a note mentioning usage of SecurityContextHolder#getContextHolderStrategy() in the deprecated constructors to explain the deprecation (similar to AuthenticationContext)
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 wonder if we should just remove the @Configuration annotation and deprecate the class for 24.8
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.
Yes, that would be better. I initially removed the class to see what failed without it, but we can keep it and deprecate before complete removal.
06f63c2 to
5eb99f8
Compare
9d38154 to
4d566a5
Compare
|
One missing part: restore and deprecate |
|
| // Ensure AuthenticationUtil is wired to whichever | ||
| // SecurityContextHolderStrategy bean is in use, | ||
| // even if a custom one is provided by the application. | ||
| @Bean | ||
| SmartInitializingSingleton securityContextHolderStrategyInitializer( | ||
| SecurityContextHolderStrategy securityContextHolderStrategy) { | ||
| return () -> AuthenticationUtil.setSecurityContextSupplier( | ||
| securityContextHolderStrategy::getContext); | ||
| } |
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 defeats the purpose of having the strategy as a bean. This PR makes sense only by removing all static methods for security.
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 strategy bean enables to have a different strategies for different scopes (in the same thread). Setting a static accessor opens to the risk of using the wrong strategy if the method is called on a scope where the expected strategy is different.
To keep backwards compatibility, apps that want to use static access could still use SecurityContextHolder.getContext() by explicitly setting the strategy statically.
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 don't understand your point. AuthenticationUtil takes a Supplier<SecurityContext> so any time this is used it should call securityContextHolderStrategy.getContext(), where securityContextHolderStrategy is the defined bean.
What am I missing?
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 point is that the bean instance could be different during runtime, while here we statically set that specific securityContextHolderStrategy bean instance. This is equivalent to
SecurityContextHolder.setContextHolderStrategy(securityContextHolderStrategy)and then obtain the context statically with SecurityContextHolder.getContext().
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.
Or is SmartInitializingSingleton evaluated every time based on the current context?
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.
SecurityContextHolder.setContextHolderStrategy(securityContextHolderStrategy)
And how is this different from new AuthenticationContext(securityContextHolderStrategy) or new SpringAccessPathChecker(securityContextHolderStrategy, evaluator, vaadinProperties.getUrlMapping())?
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.
Those other beans are created explicitly with that instance: if the developer wants to provide their own bean, they explicitly pass the strategy they need.
The problem with static methods is that you don't have much control of what they return and using them in different contexts/scopes might result in unexpected instances.
If we want to keep support for static access to the security context, then better stick with
SecurityContextHolder.setContextHolderStrategy(securityContextHolderStrategy)called somewhere, but I think that should be a choice on the app side.
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 see, but I'm not sure if we can completely get rid of static methods in AuthenticationUtil.
What about a temporary workaround, like:
- add a constructor to
AuthenticationUtilthat getsSecurityContextHolderStrategyand sets it to the static field - expose
AuthenticationUtilas a bean with@ConditionalOnMissingBean - if the developer needs, it can override the bean provide the required strategy
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 wouldn't introduce a temporary workaround at this point. Let's split this change in multiple steps, maybe removing the separate configuration for the strategy bean and set it statically allowing the user to provide their own.
|
Closing this in favor of an incremental approach and a proper deprecation cycle of the static accessor to the holder strategy, with #22745 as a starting point. |



This fixes #21401 by providing a
SecurityContextHolderStrategybean as part of Spring Security auto-configuration and replaces static invocations ofSecurityContextHolder.getContext()by using the strategy bean instead.SecurityContextHolderStrategyinSpringSecurityAutoConfigurationVaadinAwareSecurityContextHolderStrategyConfigurationVaadinSecurityConfigurerbuild lifecycleVaadinWebSecurityfor backwards compatibilityAuthenticationContextandSpringAccessPathCheckerAuthenticationUtilmethodsBreaking changes
VaadinAwareSecurityContextHolderStrategyConfigurationhas been removed — mild since it was purely for internal useSpringSecurityAutoConfiguration::accessPatchCheckersignature has changed to include the strategy parameter — mild since this class shouldn't be extended (better have package-private bean methods)VaadinAwareSecurityContextHolderStrategyConfigurationmight expect that custom strategy to be used by Flow, instead of the bean — those apps should now provide the custom strategy as a bean (if they expect Flow to use it)DRAFT Tests setting the strategy statically must be updated (some already are)