Hi there.
I need to make a login form using tapestry 5 (to have a consisten look'n'feel with the rest of the site, and also because I need to process user-submitted data with some code of mine and I cannot do this in a filter).
Tapestry5 forms doesn't allow to choose field names (that is: I cannot have field names like j_username/j_password; neither can I submit to j_spring-securty-check).
I want to to manage these values with my code BEFORE that the authentication occurs, so I was in need to call my tapestry methods and THEN call authenticationManager.authenticate(request) as in the example of chapter 5.3 of the spring security manual.
Alas, to do this I need to access the AuthenticationManager from my tapestry methods.
I guessed that the proper way to look for a bean inside a web app was to call something similar to this:
as found in various examples around the web, but I was halted by the (in)famous "BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext..."Code:ApplicationContext context = new XmlWebApplicationContext(); myAuthenticationManager = (Authenticationmanager) context.getBean(AuthenticationManager.class);
So I called refresh... just to find that I needed to set a ServletContext to the XmlWebApplicationContext()... BUT I HAVE NO SERVLET CONTEXT in a tapestry5 pojo!
After struggling with bean factories, listeners and friends I found a way to overcome this problem:
1) I declared a bean that has a static method to execute authentication and a static AuthenticationManager variable;
2) I passed the AuthenticationManager with a ref inside security.xml to this bean;
3) and then, in my code, I called the static method within my bean that, being static, can be called even if I have no access to the bean instance. (see code at the end for details)
This seems to be very ugly... Is there any better way to do this? That is:
Question 1: what is the best way to obtain a spring bean from a web app?
Question 2: is there any better way to access the authentication manager ?
Question 3: is any other way to execute a programmatic authentication from my code?
Thanks, GHJoke
--- CODE INSIDE MY BEAN ---
--- XML INSIDE MY SECURITY.XML CONFIGURATION FILE ---Code:class AuthenticationManagerHandler { ... private static AuthenticationManager s_authenticationManager=null; AuthenticationManager getAuthenticationManager(){ return s_authenticationManager; } public void setAuthenticationManager(AuthenticationManager i_authenticationManager) { s_authenticationManager=i_authenticationManager; } public static boolean executeLogin(String i_username, String i_password, List<GrantedAuthority> i_authorities) { if (s_authenticationManager == null) { return false; } try { Authentication l_request = new UsernamePasswordAuthenticationToken(i_username, i_password, l_authorities); Authentication l_result = s_authenticationManager.authenticate( l_request ); SecurityContextHolder.getContext().setAuthentication( l_result ); } catch (Exception l_exception) { return false; } return true; } ... }
--- CODE INSIDE MY TAPESTRY METHOD ---Code:... <bean id="myAuthenticationManagerHandler" class="com.amadego.AuthenticationManagerHandler"> <property name="authenticationManager" ref="springAuthenticationManager" /> </bean> <authentication-manager alias="springAuthenticationManager"> ... <authentication-manager> ...
Code:... do my housekeeping ... boolean isAuthenticated=AuthenticationManagerHandler.executeLogin("myuser","mypassword",myAuthotities); if (! isAuthenticated) { // KO, stop the user! ... return; } //OK, go on ...


