Announcement Announcement Module
Collapse
No announcement yet.
Programmatically authenticating a user (tapestry5/spring-security3) Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Programmatically authenticating a user (tapestry5/spring-security3)

    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:
    Code:
    ApplicationContext context = new XmlWebApplicationContext();
    myAuthenticationManager = (Authenticationmanager) context.getBean(AuthenticationManager.class);
    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..."

    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 ---

    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;
     }
     ...
    }
    --- XML INSIDE MY SECURITY.XML CONFIGURATION FILE ---

    Code:
    ...
    <bean id="myAuthenticationManagerHandler" class="com.amadego.AuthenticationManagerHandler">
    	<property name="authenticationManager" ref="springAuthenticationManager" />
    </bean>
    
    <authentication-manager alias="springAuthenticationManager">
           ...
    <authentication-manager>
    ...
    --- CODE INSIDE MY TAPESTRY METHOD ---

    Code:
    ... do my housekeeping ...
     boolean isAuthenticated=AuthenticationManagerHandler.executeLogin("myuser","mypassword",myAuthotities);
     if (! isAuthenticated) {
        // KO, stop the user!
        ...
        return;
     }
      //OK, go on
      ...
Working...
X