Didn't mean much by information at the time.  But, after looking at the
code, I suppose my concern would be with getAuthorizationInfo() of the
AuthorizingRealm - if caching is enabled, it seems to me that your
technique might be dangerous.

Thanks,
Jared

On 07/08/2011 04:21 PM, Les Hazlewood wrote:
> Hi Jared,
>
> What do you mean exactly?  What information?
>
> Cheers,
>
> Les
>
> On Fri, Jul 8, 2011 at 11:54 AM, Jared Bunting
> <[email protected]> wrote:
>> Les,
>>
>> I like the approach.  Do you have to be concerned with the realm caching
>> information though?
>>
>> Thanks,
>> Jared
>>
>> On 07/08/2011 01:51 PM, Les Hazlewood wrote:
>>> Here's how we do this in our own Shiro-based multi-tenant application:
>>>
>>> We have a TenantFilter (a Servlet Filter) that filters all incoming
>>> HTTP requests (only HTTP/S communication is performed by clients, so
>>> we only have to worry about the HTTP protocol).  The TenantFilter
>>> inspects the hostname specified in the request (e.g.
>>> companyname.mysite.com).  We parse out 'companyname' and perform a
>>> lookup in our data store for the Tenant entity corresponding to that
>>> name.
>>>
>>> Once the Tenant object is acquired we bind it to a ThreadLocal so it
>>> is available for the duration of the request (the TenantFilter ensures
>>> it is removed from the thread, even in the event of any exception to
>>> ensure the thread remains 'clean' in a thread-pooled environment).
>>>
>>> All tenant-related query logic is handled in our DAO layer - the rest
>>> of the codebase (including Shiro), never 'knows' about the Tenant
>>> concept.  The DAOs are the ones that inspect the Tenant ThreadLocal
>>> and manipulate the query.
>>>
>>> For example, you might have a UserDAO that looks up a User by
>>> username, and your Realm implementation would use the UserDAO to
>>> acquire the User object.
>>>
>>> Your Realm's doGetAuthenticationInfo implementation might look
>>> something like this:
>>>
>>> ========================
>>> UsernamePasswordToken upToken = (UsernamePasswordToken) token;
>>> String username = upToken.getUsername();
>>>
>>> User user = userDAO.findByUsername(username);
>>> if (user == null) {
>>>     throw new UnknownAccountException("No account found for username
>>> '" + username + "'");
>>> } else if (user.isDisabled()) {
>>>     throw new DisabledAccountException("The account for username '" +
>>> username + "' is disabled");
>>> } else if (user.isLocked()) {
>>>     throw new LockedAccountException("The account for username '" +
>>> username + "' is locked");
>>> }
>>>
>>> SimpleAccount shiroAccount = new SimpleAccount(user.getId(),
>>> user.getHashedPassword(), getName());
>>> shiroAccount.setCredentialsSalt(new
>>> SimpleByteSource(Base64.decode(account.getPasswordSalt());
>>>
>>> return shiroAccount;
>>> ========================
>>>
>>> Notice how we didn't reference the tenant anywhere?
>>>
>>> The UserDAO implementation is the thing that inspects the Tenant
>>> ThreadLocal.  It's 'findByUsername' implementation can do this for
>>> example (e.g. using JPA or Hibernate queries):
>>>
>>> User findByUsername(String username) {
>>>     Object[] queryParams = {username, TENANT_THREAD_LOCAL.get().getId()};
>>>     return executeQuery("from User u where u.username = ? and
>>> u.tenant.id = ?", queryParams);
>>> }
>>>
>>> We consider the Tenant concept to be a more infrastructural/EIS-level
>>> concern and not something that should bubble up into code much (if at
>>> all).  The TenantFilter and the DAOs encapsulate this logic quite
>>> nicely away from the rest of the application.
>>>
>>> HTH!
>>>
>>> Best regards,

Reply via email to