rianna rianna - 3 months ago 6
Java Question

JSP: How to check if a user is logged in?



I'm learning Java Web, but I have some problems and I need help.
I use a template.jsp in which I include header.jsp, footer.jsp, login.jsp (the left side of the template ) and

${param.content}.jsp
. For each page named X.jsp I made another jsp with the following content, because I want each page to have the same layout:

<jsp:include page="template.jsp">
<jsp:param name="content" value="X"/>
<jsp:param name="title" value="Start navigate"/>`enter code here`
</jsp:include>


When I click on the Review link,for example, I want to be redirect to Review.jsp, but I have some problems.
In footer.jsp I have something like this:

(...)
< a href =" Review.jsp "> Review </a>
(...)


After login, I try to click Review, it sends me to the Review.jsp, but it shows me that I'm not logged in. I use Spring Framework, Tomcat 7, Eclipse, MySQL. When I log in, I create a cookie:

String timestamp = new Date().toString();
String sessionId = DigestUtils.md5Hex(timestamp);
db.addSession(sessionId, username, timestamp);
Cookie sid = new Cookie("sid", sessionId);
response.addCookie(sid);


For each method, I have something like this (I saw this in a tutorial):

@RequestMapping(value = "/writeReview", method = RequestMethod.GET)
public String nameMethod(@CookieValue("sid") String sid,...)


Using the sid, I can find out who's the user. I have a database with the user's account and some other tables. The problem is that when I click review or any other, it shows me that I'm not logged in. What can I do?

UPDATE:

I use JavaBean for user and login.jsp. The JSP that has the text box for the login, I have a GET method when I click on the button to log in.

@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView createCookie(
@RequestParam("username") String username, @RequestParam("password") String password,
HttpServletRequest request, HttpServletResponse response) throws SQLException {
//code for creating the cookie here, after testing if the user is in my database
}


For each page, I send the sid and I have an attribute for the model, username:

public String methodName(@CookieValue(required = false) String sid, Model model) {
if (sid != null) {
User user = getUserBySid(sid);
model.addAttribute("user", user);
}
(..other data.)
return "nameJSP.jsp";
}


I check in each JSP if the username is not empty, so that's how I see if a user is logged in. The application goes well, it passes parameters if I don't click on the links from the header or footer. The problem is that I have to pass , let's say, a parameter from a JSP who's the actual content of the layout to the JSP referred by the footer and this JSP will be the next content of my layout. The layout only recognize content and title:

<title>${param.title}</title>
(I didn't paste all the code, I use a table <table>....)
<%@ include file="header.jsp"%>
<%@ include file="login.jsp"%>
<jsp:include page="${param.content}.jsp"/>
<%@ include file="footer.jsp"%>


So how can I include a parameter in this JSP which will be received from another JSP? Also it will have to be accessed by layout.jsp and sent to the footer or the header?

<jsp:include page="layout.jsp">
<jsp:param name="content" value="X"/>
<jsp:param name="title" value="Start navigate"/>
</jsp:include>

Answer

To pass some parameter(s) to the included JSP:

<jsp:include page="somePage.jsp" >
    <jsp:param name="param1" value="someValue" />
    <jsp:param name="param2" value="anotherParam"/>
    ....
</jsp:include>

You are already doing it.

OK, the details of the question is not very clear, but I get the idea.
One of the solutions could be the following.

In your Login action, if the authentication was successful, create HttpSession and set an attribute for the authenticated User:

if (/* authentication was successfull */) {
    request.getSession().setAttribute("loggedInUser", user);
    ...
}

And in the code where you are controlling if the user is logged in just check the presence of the appropriate HttpSession attribute:

HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("loggedInUser") == null) {
    // user is not logged in, do something about it
} else {
    // user IS logged in, do something: set model or do whatever you need
}


Or in your JSP page you can check if the user is logged in using JSTL tags as showed by BalusC in the example here:

...
<c:if test="${not empty loggedInUser}">
    <p>You're still logged in.</p>
</c:if>
<c:if test="${empty loggedInUser}">
    <p>You're not logged in!</p>
</c:if>
...

Filters to the rescue

But usually, you check if the user is logged in to restrict access to some pages (so only authenticated user could access them). And you write some class that implements javax.servlet.Filter.

Here is an example of the LoginFilter from one of my projects:

package com.example.webapp.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * The purpose of this filter is to prevent users who are not logged in
 * from accessing confidential website areas. 
 */
public class LoginFilter implements Filter {

    /**
     * @see Filter#init(FilterConfig)
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute("loggedInUser") == null) {
            response.sendRedirect(request.getContextPath() + "/login.jsp");
        } else {
            chain.doFilter(request, response);
        }
    }


    /**
     * @see Filter#destroy()
     */
    @Override
    public void destroy() {}

}

In this project I used plain servlets and JSP without Spring, but you'll get the idea.

And of course, you must configure web.xml to use this filter:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    ...
    <filter>
        <filter-name>Login Filter</filter-name>
        <filter-class>com.example.webapp.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Login Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>


Note:
If you are using a Web Container or Application Server that supports Servlet version 3.0 and higher then you can annotate your filter class with @WebFilter annotation in which case there is no need to configure the filter in the deployment descriptor (web.xml). See an example of using @WebFilter annotation and more Filter related information here.

Hope this will help you.

Comments