Tags
The problem: hardcoded role-based authorization
One of the challenges around using Spring Security is that the examples—both in the documentation and on the web—tend to promote an overly-simple approach to role-based authorization, hardcoding roles in the source in a non-configurable fashion. For example:
@PreAuthorize("hasRole('facultyMember')")
public Newsletter getFacultyNews() { ... }
(Assume for the sake of example that ACL-based authorization is overkill for the method in question. The user either has permission to read faculty newsletters or not.)
The problem is that when we decide to make a change—for example, maybe teaching assistants should be allowed to read the faculty newsletters too—we have to go into the code to make a change:
@PreAuthorize("hasRole('facultyMember') or hasRole('teachingAssistant')")
public Newsletter getFacultyNews() { ... }
For domain object security there’s no problem because the permissions are cleanly separated from roles. We can map associate individual permissions on domain objects with users and roles as we wish. So the code contains annotations like
@PreAuthorize("hasPermission(#message, write)")
public void editMessage(Message message) { ... }
and all is good. We probably won’t need to change the relationship between the permission and the method itself; we’ll only need to change who (which users/roles) actually has the write permission on the message in question, and we can do that in the database. So that is nice, and we want the same thing for role-based authorization.
Solution: use granted authorities to model permissions, not roles
Here we assume an authentication source that models the desired relationship between users, roles and permissions. The typical relationship would be a many-many relationship between users and roles, and a many-many relationship between roles and permissions. For example:

It would be possible to have a direct relationship between users and permissions too (say to allow for the assignment of fine-grained permissions to specific users in addition to assigning roles), if that were desired.
The schema can be part of some standard authentication source or it can be a custom UserDetailsService; it doesn’t matter.
At the end of the day we need to transform our user representation into a UserDetails, and the trick is to map permissions—not roles—to GrantedAuthority objects to support the getAuthorities() contract on the UserDetails interface. We still have roles, but they matter only insofar as they help to bundle permissions up into convenient packages. The UserDetails implementation will probably expose the roles, but the UserDetails interface simply exposes the permissions (not the roles) via the getAuthorities() method.
It’s really that simple, and the final result is that we can avoid hardcoding roles in the code:
@PreAuthorize("hasRole('PERM_READ_FACULTY_NEWS')")
public Newsletter getFacultyNews() { ... }
As an aside, the predicate name hasRole rather than hasAuthority is a minor annoyance since permissions aren’t roles. The backing check is against a GrantedAuthority and so hasRole() seems to reflect either the intended or the typical use of GrantedAuthority.
This tip is save my tons of time. Thanks a lot.
Great tip – this goes in line with the best practice I heard described by a spring security guy in an online video somewhere once.
(I also find it odd how they say hasRole instead of hasAuthority since it’s grantedAuthorities it is checking against)
It seems realy good but, how should I implement this solution?
Can you provide a more specific example?
Once a time, I’ve made something that seems similar to what you said.. (I’m not so shure, couse your tip is too abstract to me).. I just created tables to match user, role and permissions and configured a jdbc-user-service through the users-by-username-query and authorities-by-username-query atributes by using joins with all the tables.
In this way, when the spring used the query to get the authorization, I was giving the permissions obtained through the joins.
For example, I inserted one permission on the table with the name ‘ROLE_EDIT_DOCUMENT’ and used this like if it was a permission just to avoid spring hanging on me about the name diferent from ‘ROLE_**’.
But it seems ugly to make things work this way. This solution looks quite simple but I’m looking for a bether one.
.. then can you give some example so I can understand better?.. or you’re talking just about this same trick I made?
I’m not sure but I think that is to override the method in User class
For me in Groovy, replace
Set getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
with
Set getAuthorities() {
Set list = UserRole.findAllByUser(this).collect { it.role } as Set
def roles = new HashSet()
roles.addAll(list)
list.each {
//psudo code
add all permission relate to each role to ‘roles’ as Role object
}
}
If I’m wrong, please anyone help
Great posting! Thanks a lot.
The hasRole() instead of hasAuthority() shows that Spring Security isn’t as mature as other parts of the system.
Wouldn’t be surprised to see a hasAuthority() method (as a synonym with hasRole()) in the future.
Thanks for the great tip — Regarding the “hasRole(…)” predicate in the @PreAuthorize annotation, you should be able to replace it with “hasAuthority(…)” with identical functionality (see http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/index.html).
In fact, “hasAuthority(…)” is just an alias for “hasRole(…)” (see https://fisheye.springsource.org/browse/spring-security/core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java?r=1c8d28501c6e7bf68f6a8f1c3027e88b256a7acb).
I have verified that this works at least with Spring Security 3.0.5.
Oops, the first link should be http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/access/expression/SecurityExpressionRoot.html
tHERE IS A SECURITY MODEL USED IN PHYSICAL SECURITY THAT SEEMS MORE AND MORE APPROPRIATE IN WEB BASED APPS. Hmmm, sorry for previous caps, cap key was on. Actions and web links have permissions, i.e., I can get into the building, to a certain floor, certain days of the week. But If I want access to the a safe deposit box, I need another layer of security.
This would be equivalent to normal framework (Spring, Symfony, Ruby on Rails, CakePHP) letting a user in the door via web pages, but having the Database or the ORM allow per record permissions, the safe deposit box is the last layer of security.
So if the gate guard is in the bathroom (some code screwed up the web interface), the safedeposit boxes (per record permissions) keeps the bad guy from getting easity into the family jewels
Hi,
It seems really cool solution.
But can u please tell me how to model permission instead of roles in Granted Authorities.
Can you please provide some code lines?
If you can share some sample application using above features then it will be better than best.
can you please post the security xml configuration file ?
Is there a way to achieve this using ldap authorization?
Hi,
There post is very interesting and I have question to Spring security. I need to implement a Cookie Based stateless authentication with Spring Security so that to make my application scalable.
Does anyone have any idea how to proceed.
Many thanks.
Shameem