RTF
RTF

Reputation: 6504

Apache Shiro roles and permissions not working

I'm using Apache Shiro (v1.2.3) and I have username/password authentication setup correctly and it's working (I'm storing the password hashes and salts in a remote database). I'm now trying to setup permissions using roles. I have a single realm that extends AuthorizingRealm e.g.

public class MyRealm extends AuthorizingRealm {

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        // no problems here...
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principles) {
        Set<String> roles = // get the roles for this user from the DB
        LOG.info("Found roles => " + roles.toString());
        return new SimpleAuthorizationInfo(roles);
    }

}

My shiro.ini looks like this:

[main]
myRealm = ie.enki.closing.users.MyRealm

credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
credentialsMatcher.storedCredentialsHexEncoded = false
credentialsMatcher.hashIterations = 1024

myRealm.credentialsMatcher = $credentialsMatcher

cacheManager = org.ehcache.integrations.shiro.EhcacheShiroManager
securityManager.cacheManager = $cacheManager

[roles]
admin = *
staff = resource_1:action_1

The relevant startup logging reports that ehcache is being setup correctly but before it does, it also mentions this:

[main] INFO org.apache.shiro.realm.text.IniRealm - IniRealm defined, but there is no [users] section defined. This realm will not be populated with any users and it is assumed that they will be populated programatically. Users must be defined for this Realm instance to be useful.
[main] INFO org.apache.shiro.realm.AuthorizingRealm - No cache or cacheManager properties have been set. Authorization cache cannot be obtained.
...
some ehcache setup logging...

In my testing, currentUser.isPermitted("resource_1:action_1") returns false even though my logging says that I do have the admin role (I've tried it with the staff role too).

The shiro docs talk about setting up a [users] section in the shiro.ini and assigning roles to users like:

[users]
some_user = password, role1, role2

...but I don't want to define users and their passwords in the ini file. That's what my database is for. Have I misunderstood something in the configuration?

After going through the docs again, it seems that the [roles] section is only applicable if you're using the [users] section to define a small number of static users. If that's true, how do you associate roles with permissions for users defined in a database. The docs that might reveal this info are incomplete.

Upvotes: 0

Views: 2446

Answers (1)

Daniel Bickler
Daniel Bickler

Reputation: 1140

When you're not using IniRealm, you don't directly map Roles -> Permissions. You have to tell Shiro what permissions a User has with SimpleAuthorizationInfo's addStringPermissions or addObjectPermissions and if you're using roles to assign groups of permissions manually retrieve those.

There are multiple ways to do this depending on your app. Without knowing how complex your application is, it's difficult to recommend an approach. For maximum flexibility, you can create 3 database tables: USER_PERMISSIONS, ROLE_PERMISSIONS, and USER_ROLES.

If you're only doing permission checks, I'd recommend doGetAuthorizationInfo only retrieve the permissions assigned to a user. Roles would only be used on the front-end to assist in assigning groups of permissions to certain users. This is the Explicit Role recommended by Shiro in Roles.

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principles) {
    Set<String> permissions = // get the permissions for this user from the DB
    SimpleAuthorizationInfo simpleAuth = new SimpleAuthorizationInfo();
    simpleAuth.addStringPermissions(permissions);
    return simpleAuth;
}

P.S. I would remove the [roles] section and explicitly define your realm to Shiro. Implicit Assignment is not recommended. To do this, add the following line to your configuration after removing [roles].

securityManager.realms = $myRealm

Upvotes: 2

Related Questions