Grails Webdav Plugin with Apache Shiro causes Hibernate LazyInitializationException

We use Grails 2.1 with Apache Shiro 1.1.3 as security layer which handles the user authentication such as login via web app or webdav. To provide an easy and flexible file service we use webdav plugin 3.0.1. It hides the complexity of the HTTP file protocol webdav and gives a simple interface to work with virtual network filesystem structure.

When a user tries to login, our SystemDBRealm authenticates the given user with its password against the database and does other checks as well. These checks include the validation of the user role. The user role is modeled via SystemUserRoleRel within our grails domain model. SystemUserRolRel has two fields: user and role which links the SystemUser and SystemRole domain models together. Hibernate loads these models lazy in special hibernate proxies. These model proxies are loaded on demand to proper domain model instances which requires a valid hibernate session.

To check that given user has a valid role we execute following code (the code is simplified to depict the problem):

def user = SystemUser.findByUsername(username)
def standardRole = SystemRole.findByName('Standard')
def hasStandardRole = SystemUserRolRel.findAllByUser(user).find { it.role == standardRole } != null

On a normal login via browser SystemDBRealm has a hibernate session and can resolve the it.role hibernate proxy within the find closure find { it.role == standardRole }.

In case of a login via Webdav (e.g. through cadaver, a command line webdav client), the user is authenticated via BasicHttpAuthenticationFilter of shiro. As described in the Basic HTTP Auth with Shiro in Grails this basic authentication filter is configured in config.groovy like this:

security.shiro {
        authc.required = false
        filter.config = """\
[main]
authcBasic = org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
authcBasic.applicationName = Rewoo World

[urls]
/webdav/** = authcBasic
"""
}

The BasicHttpAuthenticationFilter extracts the user password token and returns it to shiro. Shiro processes this authentication token in the SystemDBRealm like the browser based login. But now the hibernate session is missing and the find closure find { it.role == standardRole } throws a hibernate LazyInitializationException: it.role can not be resolved.

To solve this issue we use the withNewSession closure of an arbitrary domain model class to wrap the authentication code defined above (in our case we choose the SystemUser class but another class should be ok as well):

SystemUser.withNewSession {
  def user = SystemUser.findByUsername(username)
  def standardRole = SystemRole.findByName('Standard')
  def hasStandardRole = SystemUserRolRel.findAllByUser(user).find { it.role == standardRole } != null
}

Now a hibernate session is bound to the closure and it.role hibernate proxy can be resolved again.

PS: A ticket is filed at GPWEBDAV-18 for this issue. Comments are welcome.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s