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