webtier@glassfish.java.net

Problems with maintaining a container secured session after login() call

From: <webtier_at_javadesktop.org>
Date: Wed, 03 Mar 2010 13:29:36 PST

I have a working JSF webapp that handles user registration and login, etc. and I have been trying to hook it up to the built-in J2EE container manager security feature.

I am using Glassfish v3 and Mojarra 2.0.2

I'm about 95% of the way there, I have successfully completed the following things:

1. Created a JDBC realm in the Glassfish Server Admin
2. Linked it with my users and groups tables in my database
3. Added security constraints to web.xml
4. Added a call to HttpServletRequest.login() to my login JSF page
5. Verified that the login() call worked -- the registered user validates correctly
6. Successfully forwarded user on to protected page.

Frustratingly, though, I just can't seem to get the authorization to stick. The protected page is very simple -- it's a SessionBean with a counter and a commandButton which, when clicked simply increments the counter and reloads the same page. I have verified that this page works fine when security is not enabled.

The problem is that even though I get to that page in the secure part of the application, and the UserPrincipal and Role in the @PostConstruct method are present, when I click the button, I get redirected back to the login page again. Every time.

I've tried everything I can think of but I can't get it to work -- the session cookie applied by the container seems to be present and consistent, but I keep losing the authentication no matter what I try.

I get the feeling that I might be missing something, but having trawled through all kinds of documentation and blog posts and forum comments, I can't find what that might be.

This is the code:

[b]From LoginUser.java[/b]
[code]
              try {
                  HttpServletRequest request = ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest());
                  HttpServletResponse response = ((HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse());
                  request.login(name, validPass);
                  System.out.println("Logged In!");
                  boolean valid = request.authenticate(response); // returns true
                  System.out.println("Authenticated! " + valid);
                  System.out.println("Is user? " + request.isUserInRole("user")); // returns true
                  System.out.println("Principal: " + request.getUserPrincipal()); // returns userid as expected
                  System.out.println("Auth Type: " + request.getAuthType()); // returns LOGIN
                  System.out.println("Remote User: " + request.getRemoteUser()); // returns userid as expected
               } catch (IOException ex) {
                  System.out.println("Not able to authenticate!");
                  Logger.getLogger(LoginUser.class.getName()).log(Level.SEVERE, null, ex);
               } catch (ServletException ex) {
                  System.out.println("Not able to login!");
                  Logger.getLogger(LoginUser.class.getName()).log(Level.SEVERE, null, ex);
               }
               validated = true;
            }
     ...
      return validated ? "/lobby/lobbyHome" : null; // (/lobby/* is in constrained area of site)
   }
[/code]
[b]LobbyHome.java[/b]
[code]
@Named
@SessionScoped
public class LobbyHome implements Serializable {

   private int counter;

   // Called after logged in successfully, and the page is displayed correctly
   @PostConstruct
   public void initView() {
      System.out.println("lobby instantiated.");
      counter = 1;
      try {
         HttpServletRequest request = ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest());
         HttpServletResponse response = ((HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse());
         boolean valid = request.authenticate(response);
         System.out.println("Authenticated! " + valid); // Returns true
         System.out.println("Is user? " + request.isUserInRole("user")); // Also returns true
      } catch (IOException ex) {
          ...
      } catch (ServletException ex) {
         ...
      }

   }

   // This method should be called when commandButton clicked, but when
   // security is enabled, it is never called -- just redirects to the login page again.
   public String addOne() {
      System.out.println("In addOne");
      counter++;
      return null;
   }

   // Getters and setters
   public int getCounter() {
      return counter;
   }

   public void setCounter(int counter) {
      this.counter = counter;
   }
}
[/code]
I believe my security configuration is set up correctly because when I access the protected page I am redirected to the login page, where the user is successfully logged in via the request.login() API call, and then I can send the user to the protected page.

But once the user is there, as soon as he tries to do anything, like click that counter button, the logged in authenticated session just evaporates. I looked through a FINE level of tracing but could find nothing to indicated any problems. The user is simply just not logged in any more when the Faces servlet is called in response to the h:commandButton click.

If I could get my hands on a working example that I could play with -- one that actually does more than just login and logout again like the simple security sample supplied with Glassfish -- then perhaps I can figure out what I am doing wrong, but for now I am out of ideas.
[Message sent by forum member 'tacitust' (tacitus_at_yahoo.com)]

http://forums.java.net/jive/thread.jspa?messageID=389911