Spring Security with roles and permissions

I'm the author of the article in question.

No doubt there are multiple ways to do it, but the way I typically do it is to implement a custom UserDetails that knows about roles and permissions. Role and Permission are just custom classes that you write. (Nothing fancy--Role has a name and a set of Permission instances, and Permission has a name.) Then the getAuthorities() returns GrantedAuthority objects that look like this:

PERM_CREATE_POST, PERM_UPDATE_POST, PERM_READ_POST

instead of returning things like

ROLE_USER, ROLE_MODERATOR

The roles are still available if your UserDetails implementation has a getRoles() method. (I recommend having one.)

Ideally you assign roles to the user and the associated permissions are filled in automatically. This would involve having a custom UserDetailsService that knows how to perform that mapping, and all it has to do is source the mapping from the database. (See the article for the schema.)

Then you can define your authorization rules in terms of permissions instead of roles.

Hope that helps.


The basic steps are:

  1. Use a custom authentication provider

    <bean id="myAuthenticationProvider" class="myProviderImplementation" scope="singleton">
    ...
    </bean>
    

  2. Make your custom provider return a custom UserDetails implementation. This UserDetailsImpl will have a getAuthorities() like this:

    public Collection<GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> permissions = new ArrayList<GrantedAuthority>();
        for (GrantedAuthority role: roles) {
            permissions.addAll(getPermissionsIncludedInRole(role));
        }
        return permissions;
    }
    

Of course from here you could apply a lot of optimizations/customizations for your specific requirements.


To implement that, it seems that you have to:

  1. Create your model (user, role, permissions) and a way to retrieve permissions for a given user;
  2. Define your own org.springframework.security.authentication.ProviderManager and configure it (set its providers) to a custom org.springframework.security.authentication.AuthenticationProvider. This last one should return on its authenticate method a Authentication, which should be setted with the org.springframework.security.core.GrantedAuthority, in your case, all the permissions for the given user.

The trick in that article is to have roles assigned to users, but, to set the permissions for those roles in the Authentication.authorities object.

For that I advise you to read the API, and see if you can extend some basic ProviderManager and AuthenticationProvider instead of implementing everything. I've done that with org.springframework.security.ldap.authentication.LdapAuthenticationProvider setting a custom LdapAuthoritiesPopulator, that would retrieve the correct roles for the user.

Hope this time I got what you are looking for. Good luck.