You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Philippe Laflamme <tw...@gmail.com> on 2011/03/16 21:39:19 UTC

Multiple realms and roles

Hi,

I'm using a multi-realm setup where some realms provides users and roles and
another provides permissions.

So for example, one realm is an LDAP realm that provides usernames and roles
from the LDAP groups. I want my second realm to provide permissions for
these username, but also for the roles.

Returning permissions is done in a doGetAuthorizationInfo() method on my
custom realm (which hits a database table). I use getPrimaryprincipal()
which provides my unique user ID. But I cannot see any way to lookup
permissions based on the user's roles. The PrincipalsCollection doesn't seem
to provide these. Should I be overriding some other method of
AuthorizingRealm?

How can I lookup permissions in one realm for a role defined in a different
realm?

Thanks,
Philippe

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6178792.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Multiple realms and roles

Posted by Jared Bunting <ja...@digitalreasoning.com>.
I have extended and hacked WildcardPermission so that my custom permissions are resolved when the user specifies WildcardPermissions.  I feel that the inability to interact with WildcardPermission is a deficiency in Shiro.  

Here's my hack - I extend this and pass those permissions to "checkPermission".  I've no idea if this is the best way to go about this.  Feel free to use the code:

/**
 * Extension of WildcardPermission that allows programmatic building of the permission without appending strings together.
 */
public class BuildableWildcardPermission extends WildcardPermission
{

	private boolean caseSensitive;

	public BuildableWildcardPermission(String wildcardString, boolean caseSensitive)
	{
		super(wildcardString, caseSensitive);
		this.caseSensitive = caseSensitive;
	}

	public BuildableWildcardPermission(String wildcardString)
	{
		this(wildcardString, false);
	}

	/**
	 * Make sure they're all lowercase (if need be).
	 * 
	 * @param parts
	 */
	public void addPart(Set<String> parts)
	{
		if (!caseSensitive)
		{
			Set<String> newParts = new HashSet<String>();
			CollectionUtils.collect(parts, new Transformer<String, String>() {
				@Override
				public String transform(String s)
				{
					return s == null ? null : s.toLowerCase();
				}
			}, newParts);
			parts = newParts;
		}
		this.getParts().add(parts);
	}

	public void addPart(String part)
	{
		this.addPart(Collections.singleton(part));
	}
}


On 03/18/2011 03:36 PM, Philippe Laflamme wrote:
> Right, that makes sense.
> 
> I've just tried this and it would work only if I didn't have this other
> particularity in my setup! Bear with me this is not a simple case...
> 
> I have 2 realms. One is an IniRealm and another, CustomRealm. The IniRealm
> resolves WildcardPermissions and CustomRealm resolves SpatialPermissions.
> 
> I have a RolePermissionResolver set on both (through the
> ModularRealmAuthorizer). Since the RolePermissionResolver resolves
> Permission instances, it resolves to SpatialPermission instances for both.
> 
> This results in:
> * the IniRealm compares WildcardPersmission with SpatialPermission (one
> never implies the other)
> * the CustomRealm doesn't see the IniRealm roles, so it can't resolve any
> SpatialPermission
> 
> The end goal was to test SpatialPermissions within the CustomRealm: the ones
> for the user's roles with the ones obtained by parsing the permission
> strings to test...
> 
> It's clear that I need the later case: roles need to be available in my
> CustomRealm to encapsulate everything in there.
> 
> Any idea how I can go around this "limitation" and still keep extensibility
> (users can define there own authentication realms)?
> 
> Thanks,
> Philippe
> 
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6186098.html
> Sent from the Shiro User mailing list archive at Nabble.com.



Re: Multiple realms and roles

Posted by Philippe Laflamme <tw...@gmail.com>.
Right, that makes sense.

I've just tried this and it would work only if I didn't have this other
particularity in my setup! Bear with me this is not a simple case...

I have 2 realms. One is an IniRealm and another, CustomRealm. The IniRealm
resolves WildcardPermissions and CustomRealm resolves SpatialPermissions.

I have a RolePermissionResolver set on both (through the
ModularRealmAuthorizer). Since the RolePermissionResolver resolves
Permission instances, it resolves to SpatialPermission instances for both.

This results in:
* the IniRealm compares WildcardPersmission with SpatialPermission (one
never implies the other)
* the CustomRealm doesn't see the IniRealm roles, so it can't resolve any
SpatialPermission

The end goal was to test SpatialPermissions within the CustomRealm: the ones
for the user's roles with the ones obtained by parsing the permission
strings to test...

It's clear that I need the later case: roles need to be available in my
CustomRealm to encapsulate everything in there.

Any idea how I can go around this "limitation" and still keep extensibility
(users can define there own authentication realms)?

Thanks,
Philippe

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6186098.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Multiple realms and roles

Posted by Jared Bunting <ja...@digitalreasoning.com>.
On 03/18/2011 10:51 AM, Philippe Laflamme wrote:
> Thanks for you input!
> 
> I used LDAP as an example, but this also applies to any other realm, such as
> IniRealm:
> 
> [users]
> user=password,mygroup
> [roles]
> # no permissions defined here for mygroup (but there could)
> 
> And I have another realm that hits a database for fetching permissions for
> 'mygroup'. Why am I not setting a RolePermissionResolver on my IniRealm?
> Because I'm not the one writing this file. The file is left open to
> configuration by users. They are able to add other realms (LDAP, AD,
> whatever), but my applications offers a custom realm for storing
> application-specific permissions for existing users and groups. I guess I'd
> need to tell them to add my RolePermissionResolver to their configured
> realm. To me, this sounds more like a workaround, but would definitely work.

This is what I've done.  From looking at the code, it appears that this is also possible:

((ModularRealmAuthorizer)((AuthorizingSecurityManager) securityManager).getAuthorizer()).setRolePermissionResolver(rolePermissionResolver)

This sets the role permission resolver on all realms that implement RolePermissionResolverAware.  I can't see an easier way to set this - but those are the default security manager and authorizer - and it seems to me that if you're changing them then you definitely have access to do this.  It does reek a bit of relying too much on the implementation though.  Perhaps AuthorizingSecurityManager could implement RolePermissionResolverAware and do this?  (set the role permission resolver on the authorizer if it implements RolePermissionResolverAware).  Les, if you're game for this, I'll create a ticket and submit a patch.

> 
> As for roles being principals, here's my take on it:
> 
> PrincipalCollection->Roles       (AuthorizingRealm) 
> Role->Permissions                (RolePermissionResolver)
> and
> PrincipalCollection->Permissions (AuthorizingRealm) 
> 
> The first 2 methods could be re-written as:
> PrincipalCollection->Roles->Permissions (AuthorizingRealm +
> RolePermissionResolver)
> 
> Which, in a functional sense should be equivalent to:
> PrincipalCollection->Permissions (AuthorizingRealm + RolePermissionResolver)
> 
> So, functionally, a set of roles really is a equivalent to a set of
> principals as we can derive permissions from both.
> 
> If roles were part of the PrincipalsCollection, then, as you mentioned, a
> single method would ever be needed to resolve all permissions for a given
> set of principals:
> PrincipalCollection->Permissions (AuthorizingRealm)
> 
> Anyway, this won't change soon, so I'll make some modifications to "inject"
> my RolePermissionResolver into the user-configured realms.
> 
> Thanks again!
> Philippe
> 
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6185062.html
> Sent from the Shiro User mailing list archive at Nabble.com.



Re: Multiple realms and roles

Posted by Philippe Laflamme <tw...@gmail.com>.
Thanks for you input!

I used LDAP as an example, but this also applies to any other realm, such as
IniRealm:

[users]
user=password,mygroup
[roles]
# no permissions defined here for mygroup (but there could)

And I have another realm that hits a database for fetching permissions for
'mygroup'. Why am I not setting a RolePermissionResolver on my IniRealm?
Because I'm not the one writing this file. The file is left open to
configuration by users. They are able to add other realms (LDAP, AD,
whatever), but my applications offers a custom realm for storing
application-specific permissions for existing users and groups. I guess I'd
need to tell them to add my RolePermissionResolver to their configured
realm. To me, this sounds more like a workaround, but would definitely work.

As for roles being principals, here's my take on it:

PrincipalCollection->Roles       (AuthorizingRealm) 
Role->Permissions                (RolePermissionResolver)
and
PrincipalCollection->Permissions (AuthorizingRealm) 

The first 2 methods could be re-written as:
PrincipalCollection->Roles->Permissions (AuthorizingRealm +
RolePermissionResolver)

Which, in a functional sense should be equivalent to:
PrincipalCollection->Permissions (AuthorizingRealm + RolePermissionResolver)

So, functionally, a set of roles really is a equivalent to a set of
principals as we can derive permissions from both.

If roles were part of the PrincipalsCollection, then, as you mentioned, a
single method would ever be needed to resolve all permissions for a given
set of principals:
PrincipalCollection->Permissions (AuthorizingRealm)

Anyway, this won't change soon, so I'll make some modifications to "inject"
my RolePermissionResolver into the user-configured realms.

Thanks again!
Philippe

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6185062.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Multiple realms and roles

Posted by Jared Bunting <ja...@digitalreasoning.com>.
I might be missing something, but here's my take:

You have LDAPRealm and CustomRealm.  First of all, I haven't used it yet, but from what I can tell looking at the documentation, JndiLdapRealm doesn't support groups - so I'm assuming you've extended it or implemented your own.

That being said, we can take two approaches: LDAP groups are treated as roles, or LDAP groups are treated as principals.  Neither one seems less valid to me, but the solution changes depending on which one we pick.

For resolving permissions, shiro recognizes these mappings:

PrincipalCollection->Roles       (AuthorizingRealm)
PrincipalCollection->Permissions (AuthorizingRealm)
Role->Permissions                (RolePermissionResolver)

(As you can see above, Roles are not treated as Principals by default - and they are neither Principals nor Permissions, they are their own concept - although they can be used in a permission-type capacity.)

1. LDAP groups are treated as roles

I'm starting with this one because it's how I would have implemented it and what I based my previous response to you on.  The premise here is that the LDAPRealm does the first 2 mappings, and the CustomRealm does the third.

CustomRealm implements RolePermissionResolver (this doesn't really even have to be a realm...it could only implement RolePermissionResolver).  The "resolvePermissionsInRole" method should expect a string that represents an LDAP group.  It should then return a set of permissions based on this group.  How it does this internally is an implementation detail - if you use roles to apply a set of permissions to certain groups, Shiro doesn't really care.

Next you will set the CustomRealm as the RolePermissionResolver for the LDAPRealm.

LDAPRealm ldapRealm = new LDAPRealm();
ldapRealm.setRolePermissionResolver(new CustomRealm());


2. LDAP groups are treated as principals

I hadn't considered doing this before, but I like it.  This method lets us avoid the RolePermissionResolver and simply implement CustomRealm.  

CustomRealm extends AuthorizingRealm but does not do any authentication.  Instead, in its doGetAuthorizationInfo method (I think) it will pull any ldap groups out of the PrincipalCollection and lookup permissions for those.  Again, how it maps those groups to permissions is an internal detail.  Using this method, your returned AuthorizationInfo object can contain all of the roles for the principals as well as all of the permissions.



So, in conclusion, I'm not sure if I've answered your question or not, but I've taken a stab at it.  Let me know what I can clarify.

-Jared

On 03/18/2011 09:03 AM, Philippe Laflamme wrote:
> I've added a RolePermissionResolver to my realm, but I still can't get
> another realm's roles to resolve the permissions.
> 
> Seems like the RolePermissionResolver will resolve permissions for the roles
> provided by the realm itself:
> 
> AuthorizingRealm#resolveRolePermission() is the method that invokes the
> RolePermissionResolver. It is private and takes a AuthorizationInfo as an
> argument.
> 
> The AuthorizationInfo instance is built by the realm itself from the
> PrincipalsCollection. So in fact, it will never contain roles from other
> realms.
> 
> I don't see any way of looking up permissions in a custom realm for roles
> defined in another. I'm fairly confident that my use-case is valid: LDAP
> authenticates users and provides principals (usernames and groups); users
> and groups are provided permissions in my custom realm. I thought I could
> map groups to roles in Shiro and lookup permissions based on these, but
> Shiro treats roles as authorization tokens, not as principals (is this
> correct?)
> 
> Is a role a principal or a permission? I would think it's a principal since
> the use of a role is to provide permissions: either through ACL or through a
> containment check: isUserInRole().
> 
> Thanks,
> Philippe
> 
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6184615.html
> Sent from the Shiro User mailing list archive at Nabble.com.



RE: Multiple realms and roles

Posted by Philippe Laflamme <tw...@gmail.com>.
I've added a RolePermissionResolver to my realm, but I still can't get
another realm's roles to resolve the permissions.

Seems like the RolePermissionResolver will resolve permissions for the roles
provided by the realm itself:

AuthorizingRealm#resolveRolePermission() is the method that invokes the
RolePermissionResolver. It is private and takes a AuthorizationInfo as an
argument.

The AuthorizationInfo instance is built by the realm itself from the
PrincipalsCollection. So in fact, it will never contain roles from other
realms.

I don't see any way of looking up permissions in a custom realm for roles
defined in another. I'm fairly confident that my use-case is valid: LDAP
authenticates users and provides principals (usernames and groups); users
and groups are provided permissions in my custom realm. I thought I could
map groups to roles in Shiro and lookup permissions based on these, but
Shiro treats roles as authorization tokens, not as principals (is this
correct?)

Is a role a principal or a permission? I would think it's a principal since
the use of a role is to provide permissions: either through ACL or through a
containment check: isUserInRole().

Thanks,
Philippe

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6184615.html
Sent from the Shiro User mailing list archive at Nabble.com.

RE: Multiple realms and roles

Posted by Philippe Laflamme <tw...@gmail.com>.
That's exactly what I needed.

Thanks!
Philippe

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6179294.html
Sent from the Shiro User mailing list archive at Nabble.com.

RE: Multiple realms and roles

Posted by Jared Bunting <ja...@digitalreasoning.com>.
Check out RolePermissionResolver.  You can implement that and then AuthorizingRealm implements RolePermissionResolverAware so you can set your implementation on your Realm.

-Jared

-----Original Message-----
From: Philippe Laflamme [mailto:twologic@gmail.com]
Sent: Wed 3/16/2011 4:39 PM
To: user@shiro.apache.org
Subject: Multiple realms and roles
 
Hi,

I'm using a multi-realm setup where some realms provides users and roles and
another provides permissions.

So for example, one realm is an LDAP realm that provides usernames and roles
from the LDAP groups. I want my second realm to provide permissions for
these username, but also for the roles.

Returning permissions is done in a doGetAuthorizationInfo() method on my
custom realm (which hits a database table). I use getPrimaryprincipal()
which provides my unique user ID. But I cannot see any way to lookup
permissions based on the user's roles. The PrincipalsCollection doesn't seem
to provide these. Should I be overriding some other method of
AuthorizingRealm?

How can I lookup permissions in one realm for a role defined in a different
realm?

Thanks,
Philippe

--
View this message in context: http://shiro-user.582556.n2.nabble.com/Multiple-realms-and-roles-tp6178792p6178792.html
Sent from the Shiro User mailing list archive at Nabble.com.