Hi,

This post is mostly related to tapestry-security, but I hope it's ok to post
here in tapestry mailing list (now that Kalle is a committer and all.. :) )

So I finally decided to implement tapestry-security. Had a few bumps in the
road, as I will come back to, but all in all I must say it's been a
pleasure.
Using:
Tapestry 5.2.4
Tapestry-Security: 0.3.1

Initially I had a custom authentication dispatcher for restricting access,
and a cookie rememberme (also a dispatcher).

With tapestry-security and shiro I get a feature rich authentication and
authorization framework based on roles and permissions and it's been
pretty strait forward to replace the dispatchers with tapestry-security.
I have however decided to keep the cookie dispatcher as a fallback for the
users so they don't have to reauthenticate with shiro. If such a user visits
- then the user will be looked up, and logged in with shiro (now with a
shiro rememberme manager). I think it's a gentle transition.

I had some challenges along the way.
Perhaps it can be useful for others, and it would be great for some feedback
in case it can be done in a better way (or if I've just missed correct way
of configuration).

1. *Make tapestry-security localization aware*
When specifying urls for AccessControlFilters, either in shiro.ini or while
setting applicationDefaults tapestry-security does not seem to honor
localization.
So if I'm in accessing though /en paths - then I'm redirected to a /  and
loose the localization info.
I have not been able to solve this yet.

2. *shiro.ini or module configuration - I'm confused*
The tapestry-security documentation say you can configure shiro in either
shiro.ini or in module.
I might be wrong here, but it seems that from module you can only configure
redirect urls, and FilterChainDefinitions
through contributeSecurityRequestFilter.
For example I needed to implement my own RememberMeManager for customizing
the cookie ttl (I want to set either a long lived cookie or sessioncookie
depending on condition).
I first tried to do this in shiro.ini:
*[main]*
*# Objects and their properties are defined here,*
*# Such as the securityManager, Realms and anything*
*# else needed to build the SecurityManager*
*myRememberMeManager = com.movellas.web.security.MyCookieRemberMeManager*
*securityManager.rememberMeManager = $myRememberMeManager*

I can see my manager is instantiated, but somehow it's beeing discarded and
the standard CookieRememberMeManager takes precedence.
What I ended up doing is probably not recommended, but it works.
In appmodule:
*/***
* * This is probably not recommended, but we need to somehow supply our own
remembermanager.*
* * If this is specified in shiro.ini, then it will be overridden by
Tynamo's TapestryRealmSecurityManager*
* * @param manager*
* * @return*
* */*
*@Match("WebSecurityManager")*
*public static WebSecurityManager
decorateWebSecurityManager(WebSecurityManager manager) {*
* if(manager instanceof TapestryRealmSecurityManager) {  *
* MyCookieRemberMeManager cmanager = new MyCookieRemberMeManager();     *
* cmanager.setCipherKey(Base64.decode("######################=="));*
* ((TapestryRealmSecurityManager)manager).setRememberMeManager(cmanager);*
* }*
* return null;*
*}*
*
*
I get the reference to the security manger, but don't really decorate - just
change the remembermemanger. (I also change the cipherKey.)
Please let me know if someone has a better suggestion.
What can be configured from shiro.ini and what can be configured in module?
(It would seem like some part's of the ini configuration is just thrown
away.)

3.* Problems doing logout from tapestry*
(I've just found a different post regarding this with subject: "Error after
logout")
I found that when shiro is doing logout it invalidates the session in the
end.
As tapestry is using a Request service which 'shadows' the
httpservletrequest and keeps an internal state, it is not informed that the
session is actually invalidated elsewhere.
It therefore tries to access the session and exceptions are thrown. I tried
experimenting with the order of doing things, and got different exceptions.
Currently I use this variant.
Logout.java
*Object onActivate() { *
* /***
* * The order is important as shiro uses the 'real' httpsession.*
* * Upon logout shiro clears session and cache and if session is already
invalidated - an exception occur.*
* * *
* * Tapestry on the other hand uses a session facade and if the 'real'
httpsession is invalidated then the facade don't know about it as it
maintains it's own state.*
* * This causes tapestry to fail internally.*
* * *
* * So the strategy is: Let shiro perform logout, then invalidate tapestry's
session and catch IllegalStateException as result of it.*
* */ *
* //1. Logout shiro*
* securityService.getSubject().logout();*
* //2. Logout legacy*
* 
if(!Validator.isBlankOrNull(cookies.readCookieValue(CookieHelper.LOGIN_COOKIE)))
{*
* cookies.removeCookieValue(CookieHelper.LOGIN_COOKIE);*
* } *
* try {*
* Session session = request.getSession(false);*
* if(session!=null && !session.isInvalidated())*
* session.invalidate(); *
* } catch (IllegalStateException e) {*
* // could happen here if session was already invalidated outside of
tapestry *
* } *
* return Index.class;*
*}*
*
*
Thank you so much for making the tapestry-security module. For our use cases
and applications I think it's a perfect match.
>From my experience it seems to be very stable and reliable.

Thanks in advance
Magnus Kvalheim

Reply via email to