Gareth,
I think a method for retrieving an authenticated Subject's permissions is
probably not out of place in Shiro's API. There are definitely going to be
cases where it's easier/faster/more efficient to check the Subject's
permissions against a set of resources than to check the resources against
their permissions. How exactly such a thing might be implemented is probably
worthy of broader discussion. If I were to add such a feature, I'd probably
want both a simple getter (getPermissions()) as well as something that
functioned more like a callback (doWithPermissions(SomeCallback)) that would
iterate over the Subject's permissions and call my callback with each.
I think, though, to some extent, there is a belief that Shiro itself may not
need such methods, since it provides read-only access to a user/permission
model. Allow me to explain. With the current Shiro design, the expectation is
that you have built a Realm somewhere--those permissions must be loaded
somehow, and that's code Shiro doesn't include. In the system I'm currently
working on, for example, we have a ManagedDirectoryRealm. That Realm is
created/wired using Spring, in our case, but it could as easily be
created/wired using another DI framework, or Shiro's own INI config support. In
doGetAuthenticationInfo() on our Realm implementation, we rely on an AccountDao
instance which has been wired in to retrieve an Account by its e-mail address
or username. That returned Account instance, in our system, has a
getPermissions() method on it. The primary principal on the SimpleAccount
returned is the primary key ID of the Account instance in our database. Because
of these two facts, we can do something like the following:
public interface SecurityManager {
@RequiresAuthentication
long getCurrentPrincipal();
}
public class DefaultSecurityManager implements SecurityService {
@Override
public long getCurrentPrincipal() {
return (Long) SecurityUtils.getSubject().getPrincipal();
}
}
public interface AccountManager {
@RequiresAuthentication
Account getCurrentAccount();
}
public class DefaultAccountManager implements AccountManager {
@Autowired
private AccountDao accountDao;
@Autowired
private myexample.SecurityManager securityManager;
public Account getCurrentAccount() {
return accountDao.read(securityManager.getCurrentPrincipal());
}
}
This way, anything in our system which needs the Account of the logged-in user
in the executing context can get it. This is necessary because an Account has
many fields for things like name, e-mail address, username, etc., and some
parts of our system need those details. In your case, with something like this,
you would be able to get the current Account and get its permissions.
The biggest shortcoming of this approach is that you won't really have access
to a fully resolved set of Permissions (in the Shiro sense). If your version of
an "Account" relies on groups and other things to define its overall set of
permissions, this approach won't really help you as much. That's a case where
adding the ability to Shiro to retrieve the fully-resolved set of Permissions
for a Subject would be a very nice feature. It's one our own system is likely
to need, so we'd likely be very interested in collaborating with you on a
solution, if you wanted to participate in the process.
My suggestion would be to open an issue in Shiro's JIRA requesting the
getPermissions() method you're looking for, and then post about the issue on
Shiro's developers list (as opposed to its user list). I'm certain Les and
Kalle and the other committers (I'm not one, but I've been following this list
for a long time now) will have excellent ideas and feedback, and I know they're
always willing to accept a well-though-out patch.
Hope this helps,
Bryan Turner
Katasoft, Inc
P.S. As an aside, if you cast the SecurityManager instance you get from
SecurityUtils to either DefaultSecurityManager or RealmSecurityManager (which
DefaultSecurityManager extends), you can call getRealms(). In your system as
you've described it, the returned collection should have exactly 1 Realm
instance in it, which will be your Realm implementation. This goes below the
interfaces, unfortunately, but for the moment, until Shiro adds the
getPermissions() method you need, this should let you use
goGetAuthorizationInfo() to get a Subject's roles and permissions for yourself.
> Date: Sat, 30 Jul 2011 08:43:45 -0700
> From: [email protected]
> To: [email protected]
> Subject: Re: Retrieving The List Of Permissions (Or Roles) For A User
>
> Hello Phil,
>
> Thank you for responding!
>
> That is true. If I could get the Realm then I could get access to the
> AuthorizationInfo (which would give me access to the Permissions and Roles).
>
> How can the webapp get the realm though? In a web app, from SecurityUtils I
> have access to a SecurityManager or a Subject, neither of which give me
> access to the Realm.
>
> If I take a look at Spring Security (I am trying hard to avoid using Spring
> Security as it forces you to bring in the whole Spring framework -> in an
> OSGi environment there are even more dependencies), in a webapp environment,
> I can cast the User Principal from the HttpServletRequest to interface
> Authentication, then I can go call "getAuthorities" which will allow me to
> get the list of GrantedAuthorities (which can be a list of roles or
> permissions).
>
> Perhaps if subject is authenticated, Subject could have a method to return a
> list of the authorizing realms? Would that make sense?
>
> thanks,
> Gareth
>
>
>
>
>
> --
> View this message in context:
> http://shiro-user.582556.n2.nabble.com/Retrieving-The-List-Of-Permissions-Or-Roles-For-A-User-tp6634613p6636404.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>