tags:

views:

73

answers:

3

I am a newbie servlet programmer. I am trying to do this right.

I wrote a filter to intercept a servlet request and check if the URL needs the user to be logged in. If so the user gets directed to the login page. This is working. But then I want to redirect the user back the page he wanted to go to in the first place. What is the correct way to keep this state? Do I just store the URL in a data structure indexed using the session id from the cookie?

+2  A: 

You can either store it in a session or you can append it to the login url.

http://www.myexample.com/login.jsp?from=mypage.jsp

Make sure you url encode it (replacing /, &, =, etc with the appropriate escape value (%xx)) if it has a path as well as the filename.

http://www.myexample.com/login.jsp?from=mydir%2Fmypage.jsp
Tor Valamo
Thank you! I knew there will be a better way of doing this. I am a C programmer and so try to create a data structure for everything :)
+1  A: 

Don't re-invent the wheel. The Servlet API supports user/role based authentication and security. Tomcat (among others) includes built in support for authenticating using a variety of sources: xml file, database, LDAP, etc.

Asaph
how many more authentication wheels does the world need?
Tim Drisdelle
+1  A: 

I wrote a filter to intercept a servlet request and check if the URL needs the user to be logged in.

This doesn't seem to sound right. You should rather map the Filter on the same url-pattern of the Servlet, or better yet, on the servlet-name of the Servlet. This way the Filter is only invoked whenever the Servlet is called.

Back to your actual problem: when the user is not logged in, you have two options:

  1. Store the URL in session:

    if (session.getAttribute("user") == null) {
        session.setAttribute("back", httpRequest.getRequestURI());
        httpRequest.sendRedirect("login");
    } else {
        chain.doFilter(request, response);
    }
    

    which you use on login:

    User user = userDAO.find(username, password);
    if (user != null) {
        session.setAttribute("user", user);
        String back = (String) session.getAttribute("back");
        if (back != null) {
            session.removeAttribute("back");
            response.sendRedirect(back);
        } else {
            response.sendRedirect("home"); // Home page?
        }
    } else {
        // Show error?
        request.setAttribute("message", "Unknown user, please retry");
        request.getRequestDispatcher("login").forward(request, response);
    }
    
  2. Pass the URL as request parameter:

    if (session.getAttribute("user") == null) {
        httpRequest.sendRedirect("login?back=" + httpRequest.getRequestURI());
    } else {
        chain.doFilter(request, response);
    }
    

    which you pass through to subsequent request as hidden input field:

    <input type="hidden" name="back" value="${param.back}">
    

    which you use on login:

    User user = userDAO.find(username, password);
    if (user != null) {
        session.setAttribute("user", user);
        String back = request.getParameter("back");
        if (back != null) {
            response.sendRedirect(back);
        } else {
            response.sendRedirect("home"); // Home page?
        }
    } else {
        // Show error?
        request.setAttribute("message", "Unknown user, please retry");
        request.getRequestDispatcher("login").forward(request, response);
    }
    

URL encoding as some suggest is not needed as the getRequestURI() won't be decoded.

BalusC
Thanks a lot for your detailed response. Your response brings up 2 points for me that I did not address -- You said -- You should rather map the Filter on the same url-pattern of the Servlet, or better yet, on the servlet-name of the ServletIs this the standard practice? I am writing one filter per feature. For example one for logging, one for authentication checking. I map these to all jsps and servlets. I will write the second question in another comment.
You said literally that you were checking the URL in a filter to see if the user needs to be logged in. This is unnecessary if you map the filter on an `url-pattern` covering exact that URL. Or if there's already some controller servlet on the same `url-pattern`, then map it on that servlet instead. Either way the filter won't be invoked unnecessarily.
BalusC
The other question is about authentication using a database. As of now I wrote my own database connection class and am writing all the code or DB manipulation myself. I know I can use Hibernate. But is there something specific to authentication itself? What is userDAO. Also Asaph was talking about tomcat's built in security support. What is the preferred way to go for large scale applications (consumer oriented not enterprise) ?-- Thanks.
You can also make use of declarative container managed authentication as outlined here http://java.sun.com/javaee/5/docs/tutorial/doc/bncas.html That's by the way not Tomcat-specific. It's part of Java EE, so you can use it in any Java EE container.
BalusC