Search code examples
javajspshiro

Cache Invalidate not working in Shiro


We are using Apache Shiro for managing auth in our app. When using Permission I am using out of the box memory based caching and here is my shiro.ini.

In my JSP I am using shiro:taglib to check for hasPerimission and lacksPemrissons tags. If I update user role in database (hence so corresponding permissions), and when user logs-out his permissions are updated. I see unauthorized page as expected. However, the links are still rendered, which should not. These links are rendered using following syntax. (note: these links are part of common header.jsp, and included in all pages)

<shiro:hasPermission name="admin:viewPage">
        <a href="/pages/admin.jsp">Admin</a>
</shiro:hasPermission>

My class JNDIAwareJDBCRealm inherits JdbcRealm which inherits CacheManagerAware. It seems that CacheManagerAware.onLogout() clears cache.

Is it tag library doing some caching? Am I missing some implementation with caching?

My Shiro.ini file:

[main] 
jndiJdbcRealm=com.my.domian.JNDIAwareJDBCRealm
jndiJdbcRealm.jndiDataSourceName=jdbc/mySQLConnection 
jndiJdbcRealm.authenticationQuery = select password FROM users where email_id=?
jndiJdbcRealm.userRolesQuery= select role from user_roles, user where user.email_id =? AND user.id = user_roles.user_id 
jndiJdbcRealm.permissionsQuery= SELECT permission FROM role_permission WHERE role=? jndiJdbcRealm.permissionsLookupEnabled=true

bcryptCredentialsMatcher=com.my.domain.BCryptCredentialsMatcher
jndiJdbcRealm.credentialsMatcher = $bcryptCredentialsMatcher

securityManager.realms = $jndiJdbcRealm builtInCacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $builtInCacheManager

# unauthorized page
perms.unauthorizedUrl = /pages/unauthorized.jsp

(Realized that Shiro has very less documentation.)


Solution

  • I got it working. Logout workflow was wrongly using session.invalidate() in our code. So two things I required are

    1. Use correct logout workflow by invoking SecurityUtils.getSubject().logout() instead of session.invalidate().
    2. On login clear cache as follows:

    .

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
         throws AuthenticationException {
        ...
        SimplePrincipalCollection principals = new SimplePrincipalCollection(username, "jndiJdbcRealm");
        super.doClearCache(principals);
    
        ...
    }