So these are at least two questions:
- How to make the granted authorities/privileges/Roles dynamic?
- How to make the access restriction for the URLs dynamic?
1) How to make the granted authorities/privileges/Roles dynamic?
I will not answer this in great detail, because I believe this theme was discussed often enough.
The easiest way would be to store the complete user information (login, password and roles) in a database (3 Tables: User, Roles, User2Roles) and use the JdbcDetailService
. You can configure the two SQL Statements (for authentication and for granting the roles) very nicely in your xml configuration.
But then the user needs to logout and login to get these new Roles. If this is not acceptable, you must also manipulate the Roles of the current logged in user. They are stored in the users session. I guess the easiest way to do that is to add a filter in the spring security filter chain that updates the Roles for every request, if they need to be changed.
2) How to make the access restriction for the URLs dynamic?
Here you have at last two ways:
- Hacking into the
FilterSecurityInterceptor
and updating thesecurityMetadataSource
, the needed Roles should be stored there. At least you must manipulate the output of the methodDefaultFilterInvocationSecurityMetadataSource#lookupAttributes(String url, String method)
- The other way would be using other expressions for the
access
attribute instead ofaccess="hasRole('ROLE_USER')"
. Example:access="isAllowdForUserPages1To3"
. Of course you must create that method. This is called a “custom SpEL expression handler” (If you have the Spring Security 3 Book it’s around page 210. Wish they had chapter numbers!). So what you need to do now is to subclassWebSecurityExpressionRoot
and introduce a new methodisAllowdForUserPages1To3
. Then you need to subclassDefaultWebSecurityExpressionHandler
and modify thecreateEvaluationContext
method so that its first requestStandartEvaluationContext
calls super (you need to cast the result toStandartEvaluationContext
). Then, replace therootObject
in theStandartEvaluationContext
using your newCustomWebSecurityExpressionRoot
implementation. That’s the hard part! Then, you need to replace theexpressionHandler
attribute of theexpressionVoter
(WebExpressionVoter
) in the xml configuration with your new subclassedDefaultWebSecurityExpressionHandler
. (This sucks because you first need to write a lot of security configuration explicity as you can’t access them directly from the security namespace.)