Search code examples
jsfjsf-2shiro

Retrieving user information from session/authenticationtoken/cache using Apache Shiro


I am trying to build a dynamic Allowance/Permission with Apache Shiro using JPA datasource.

In the very end, everithing goes back to this class:

public class CustomAuthorizationFilter extends HttpMethodPermissionFilter {

 @Override
 public boolean isAccessAllowed(ServletRequest r, ServletResponse r, Object m) throws IOException {
  //Somehow get the user stored somewhere in the servlet memory
  SysUser loggedUser = %some_code_here%
  for (String allowance : loggedUser.getAllowances()) {
   // Do many validations
   if (pathsMatch(allowance, request)) {
    return true;
   }
  }

  return super.isAccessAllowed(request, response, mappedValue);
 }

}

The isAccessAllowed() method is fired on every request, so I don't want to get the information from the database. Shiro builds many objects regarding the user, one of them is an AuthorizationInfo. I build a CustomAuthorizationInfo where the Permissions and Allowances list are inside... but how to retrieve those without re-accessing the database?

Is it possible to store/retrieve information from the autheticated user using shiro without accessing the database?

(PS.: methods like isPermitted does not solve the problem, because I need the permission itself to use the pathsMatch() method).


Solution

  • Shiro has a caching mechanism built-in so that when the user is logged in, all build up credentials are stored in a cache and retrieved there every subsequent call as long as the user hasn't logged out.

    If you check out the source for AuthorizingRealm.getAuthorizationInfo, you can see that it retrieves the AuthorizationInfo from the cache, when caching was configured.

    http://svn.apache.org/repos/asf/shiro/tags/shiro-root-1.2.3/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java

    Check out the documentation on caching here: https://shiro.apache.org/caching.html

    The quick solution is to configure a simple memory cache:

    cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
    securityManager.cacheManager = $cacheManager
    

    This should result in only one database action per user session for retrieving the credentials.