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,
