Announcement Announcement Module
Collapse
No announcement yet.
Programmatic Authorization Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Programmatic Authorization

    I'm using the AuthenticationProcessingFilter to do request level authentification and it works fine. I have a use case however that basically says that after a user has "signed up" for the first time, they should be automagically authenticated.

    So what would be the best way to accomplish this? Would I need to do the authentication programmatically and put an Authentication in the session? I noticed in the comments in AuthenticationProcessingFilter it says to not use directly rather to use it as a filter.

    Or maybe another approach would be to forward on to the filter after signing up? I'm using Struts Tiles as well so I'm not sure the best way for forwarding on to the filter.

    Any ideas? Thanks,
    Andres

  • #2
    I think put the Authentication into the HttpSession parameter at the end of your "sign up" controller. That should work fine.

    Re the JavaDocs, they are referring to how AuthenticationProcessingFilter (and indeed all of the filters) are supposed to be deployed. They just remind they should be run via the FilterToBeanProxy, so they can operate within a managed application context.

    Comment


    • #3
      Its not quite working. In my sign up controller I'm doing this:


      Code:
      UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(webUser,webUser.getPassword());
      auth.setAuthenticated(true);
      auth.setAuthorities(webUser.getAuthorities());
      	
      HttpSession session = request.getSession();
      session.setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY, auth);
      where webUser implements the UserDetails interface. It completes ok but then when trying to access a restricted page, I get the login screen again...I'm wondering if something additional must be done to set the Authentication...Do I need to interact with the ContextHolder?

      Comment


      • #4
        So the exact problem I was having was that it would work the first time. So if I restarted the app server and then signed up, everything was ok, I would be able to access a restricted page no problem. But if I invalidated the session and then signed up again with a different user I would get the login page. The log file said:

        Code:
        2004-09-06 10:20:04,078 (net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter) - Authentication failed - adding target URL to Session: http://localhost:8081/myapp/secure/debug.htm
        net.sf.acegisecurity.AuthenticationCredentialsNotFoundException: Authentication credentials were not found in the SecureContext
        	at net.sf.acegisecurity.intercept.AbstractSecurityInterceptor.interceptor(AbstractSecurityInterceptor.java:289)
        	at net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:78)
        	at net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter.doFilter(SecurityEnforcementFilter.java:165)
        	at net.sf.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:88)
        	at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:84)
        	at net.sf.acegisecurity.ui.AbstractIntegrationFilter.doFilter(AbstractIntegrationFilter.java:170)
        	at net.sf.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:88)
        	at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:84)
        	at net.sf.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:368)
        	at net.sf.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:88)
        	at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:84)
        	at org.springframework.orm.hibernate.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:117)
        	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:73)
        	at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:84)
        	at com.caucho.server.cache.CacheFilterChain.doFilter(CacheFilterChain.java:177)
        	at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:177)
        	at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:221)
        	at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:263)
        	at com.caucho.server.port.TcpConnection.run(TcpConnection.java:323)
        	at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:430)
        	at com.caucho.util.ThreadPool.run(ThreadPool.java:377)
        	at java.lang.Thread.run(Thread.java:536)
        This would happen even if I closed all browsers. So something else was at play besides HttpSession. I found a fix, set the SecureContext to null explicitly. This does not make sense to me since I thought the SecureContext only hung around for the life of the thread, and each request is a new thread right? So anyway the code that makes it work is:

        Code:
        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(webUser,webUser.getPassword());
        auth.setAuthenticated(true);
        auth.setDetails(request.getRemoteAddr());
        auth.setAuthorities(webUser.getAuthorities());		
        
        session.setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY, auth);
        
        SecureContext context = (SecureContext)ContextHolder.getContext();
        if (context != null) {
            ContextHolder.setContext(null);
        }

        Comment


        • #5
          Take a look in AbstractIntegrationFilter as it is handling the interaction between HttpSession and ContextHolder. At the end of a request, the HttpSession will be overwritten with the contents of the ContextHolder (via a commitToContainer method).

          The reason your patch works is AbstractIntegrationFilter will only call commitToContainer if the ContextHolder is non-null. So your patch causes AbstractIntegrationFilter to skip the step that overwrites the HttpSession.

          What is of interest to me is why your ContextHolder is non-null in the first place. Because if you check the AbstractIntegrationFilter code, it only makes ContextHolder non-null if an Authentication is obtained from the extractFromContainer method (which in the case of HttpSessionIntegrationFilter reads the HttpSession). I think you've got some code somewhere that is setting up the ContextHolder (or not setting it to null at the end of a prior request), which you'll need to track down to get clarity on what is going on.

          Comment


          • #6
            Remember that this only happens on the second sign up, the first works fine. The way that I'm "logging off" is by simply invalidating the HttpSession. So I'm pretty sure that the context inside the ContextHolder is from the first sign up. Again, this super confuses me because I thought the ContextHolder only holds things for the life of a thread and we're talking about different requests.

            I'm using the org.springframework.orm.hibernate.support.OpenSess ionInViewFilter and it precedes the Acegi filter...

            Comment


            • #7
              When you "logoff" by invalidating HttpSession, is it possible AbstractIntegrationFilter doesn't get a chance to clean up the ContextHolder? It might be better to set the Authentication in the ContextHolder to null, as that way during the clean up phase of AbstractIntegrationFilter it will unbind the ContextHolder. It is important this happens, otherwise the servlet thread will be sitting there authenticated for the next web request, which is the kind of odd behaviour we're seeing.

              Comment

              Working...
              X