Java中的会话管理– HttpServlet,Cookie,URL重写

Session Management in Java Servlet Web Applications is a very interesting topic. Session in Java Servlet are managed through different ways, such as Cookies, HttpSession API, URL rewriting etc.

Java Servlet Web应用程序中的会话管理是一个非常有趣的主题。 Java Servlet中的会话通过不同的方式进行管理,例如Cookies, HttpSession API,URL重写等。

This is the third article in the series of Web Applications tutorial in Java, you might want to check out earlier two articles too.

这是Java Web应用程序系列教程中的第三篇文章,您可能也想看看前面的两篇文章。

  1. Java Web Application Tutorial

    Java Web应用程序教程
  2. Java Servlet Tutorial

    Java Servlet教程

Java中的会话管理 (Session Management in Java)

This article is aimed to explain about session management in servlets using different techniques and with example programs.

本文旨在说明有关使用不同技术和示例程序的Servlet中的会话管理。

  1. What is a Session?

    什么是会议?
  2. Session Management in Java – Cookies

    Java中的会话管理– Cookies
  3. Session in Java Servlet – HttpSession

    Java Servlet中的会话– HttpSession
  4. Session Management in Java Servlet – URL Rewriting

    Java Servlet中的会话管理– URL重写
  1. 什么是会议? (What is a Session?)

    HTTP protocol and Web Servers are stateless, what it means is that for web server every request is a new request to process and they can’t identify if it’s coming from client that has been sending request previously.

    But sometimes in web applications, we should know who the client is and process the request accordingly. For example, a shopping cart application should know who is sending the request to add an item and in which cart the item has to be added or who is sending checkout request so that it can charge the amount to correct client.

    Session is a conversional state between client and server and it can consists of multiple request and response between client and server. Since HTTP and Web Server both are stateless, the only way to maintain a session is when some unique information about the session (session id) is passed between server and client in every request and response.

    There are several ways through which we can provide unique identifier in request and response.

    1. User Authentication – This is the very common way where we user can provide authentication credentials from the login page and then we can pass the authentication information between server and client to maintain the session. This is not very effective method because it wont work if the same user is logged in from different browsers.
    2. HTML Hidden Field – We can create a unique hidden field in the HTML and when user starts navigating, we can set its value unique to the user and keep track of the session. This method can’t be used with links because it needs the form to be submitted every time request is made from client to server with the hidden field. Also it’s not secure because we can get the hidden field value from the HTML source and use it to hack the session.
    3. URL Rewriting – We can append a session identifier parameter with every request and response to keep track of the session. This is very tedious because we need to keep track of this parameter in every response and make sure it’s not clashing with other parameters.
    4. Cookies – Cookies are small piece of information that is sent by web server in response header and gets stored in the browser cookies. When client make further request, it adds the cookie to the request header and we can utilize it to keep track of the session. We can maintain a session with cookies but if the client disables the cookies, then it won’t work.
    5. Session Management API – Session Management API is built on top of above methods for session tracking. Some of the major disadvantages of all the above methods are:
      • Most of the time we don’t want to only track the session, we have to store some data into the session that we can use in future requests. This will require a lot of effort if we try to implement this.
      • All the above methods are not complete in themselves, all of them won’t work in a particular scenario. So we need a solution that can utilize these methods of session tracking to provide session management in all cases.

      That’s why we need Session Management API and J2EE Servlet technology comes with session management API that we can use.

    HTTP协议和Web服务器是无状态的,这意味着对于Web服务器,每个请求都是要处理的新请求,它们无法识别它是否来自先前一直在发送请求的客户端。

    但是有时在Web应用程序中,我们应该知道客户端是谁,并相应地处理请求。 例如,购物车应用程序应该知道谁在发送添加商品的请求以及必须在哪个购物车中添加商品,或者谁在发送结帐请求,以便可以向正确的客户收取费用。

    会话是客户端和服务器之间的转换状态,它可以包含客户端和服务器之间的多个请求和响应。 由于HTTP和Web Server都是无状态的,因此维护会话的唯一方法是在每次请求和响应中在服务器和客户端之间传递有关会话的某些唯一信息(会话ID)时。

    我们可以通过几种方式在请求和响应中提供唯一的标识符。

    1. 用户身份验证 –这是一种非常常见的方式,我们用户可以从登录页面提供身份验证凭据,然后我们可以在服务器和客户端之间传递身份验证信息以维护会话。 这不是一种非常有效的方法,因为如果同一用户从不同的浏览器登录,它将无法正常工作。
    2. HTML隐藏字段 –我们可以在HTML中创建一个唯一的隐藏字段,当用户开始导航时,我们可以为用户设置其唯一值并跟踪会话。 此方法不能与链接一起使用,因为每次从客户端到服务器使用隐藏字段进行请求时,都需要提交表单。 这也是不安全的,因为我们可以从HTML源代码中获取隐藏字段值,并使用它来修改会话。
    3. URL重写 –我们可以在每个请求和响应后附加一个会话标识符参数,以跟踪会话。 这非常繁琐,因为我们需要在每个响应中都跟踪此参数,并确保它与其他参数没有冲突。
    4. Cookies – Cookies是Web服务器在响应标头中发送的一小部分信息,并存储在浏览器的Cookies中。 当客户提出进一步请求时,它将cookie添加到请求标头中,我们可以利用它来跟踪会话。 我们可以使用cookie维护会话,但是如果客户端禁用cookie,则它将无法正常工作。
    5. 会话管理API –会话管理API建立在上述用于会话跟踪的方法之上。 所有上述方法的主要缺点是:
      • 大多数时候,我们不想只跟踪会话,我们必须将一些数据存储到会话中,以备将来使用。 如果我们尝试执行此操作,则将需要大量的精力。
      • 以上所有方法本身都不完整,在特定情况下都无法使用。 因此,我们需要一种可以利用这些会话跟踪方法在所有情况下提供会话管理的解决方案。

      这就是为什么我们需要会话管理API以及我们可以使用的会话管理API附带的J2EE Servlet技术的原因。

  2. Java中的会话管理– Cookies (Session Management in Java – Cookies)

    Cookies are used a lot in web applications to personalize response based on your choice or to keep track of session. Before moving forward to the Servlet Session Management API, I would like to show how can we keep track of session with cookies through a small web application.

    We will create a dynamic web application ServletCookieExample with project structure like below image.

    Deployment descriptor web.xml of the web application is:

    Welcome page of our application is login.html where we will get authentication details from user.

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="US-ASCII">
    <title>Login Page</title>
    </head>
    <body>
    
    <form action="LoginServlet" method="post">
    
    Username: <input type="text" name="user">
    <br>
    Password: <input type="password" name="pwd">
    <br>
    <input type="submit" value="Login">
    </form>
    </body>
    </html>

    Here is the LoginServlet that takes care of the login request.

    Notice the cookie that we are setting to the response and then forwarding it to LoginSuccess.jsp, this cookie will be used there to track the session. Also notice that cookie timeout is set to 30 minutes. Ideally there should be a complex logic to set the cookie value for session tracking so that it won’t collide with any other request.

    <%@ page language="java" contentType="text/html; charset=US-ASCII"
        pageEncoding="US-ASCII"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
    <title>Login Success Page</title>
    </head>
    <body>
    <%
    String userName = null;
    Cookie[] cookies = request.getCookies();
    if(cookies !=null){
    for(Cookie cookie : cookies){
    	if(cookie.getName().equals("user")) userName = cookie.getValue();
    }
    }
    if(userName == null) response.sendRedirect("login.html");
    %>
    <h3>Hi <%=userName %>, Login successful.</h3>
    <br>
    <form action="LogoutServlet" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>

    Notice that if we try to access the JSP directly, it will forward us to the login page. When we will click on Logout button, we should make sure that cookie is removed from client browser.

    There is no method to remove the cookie but we can set the maximum age to 0 so that it will be deleted from client browser immediately.

    When we run above application, we get response like below images.

    在Web应用程序中,Cookie经常用于根据您的选择个性化响应或跟踪会话。 在继续使用Servlet会话管理API之前,我想展示如何通过小型Web应用程序跟踪cookie的会话。

    我们将创建一个动态Web应用程序ServletCookieExample ,其项目结构如下图所示。

    Web应用程序的部署描述符web.xml为:

    我们应用程序的欢迎页面是login.html,我们将从用户那里获取身份验证详细信息。

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="US-ASCII">
    <title>Login Page</title>
    </head>
    <body>
    
    <form action="LoginServlet" method="post">
    
    Username: <input type="text" name="user">
    <br>
    Password: <input type="password" name="pwd">
    <br>
    <input type="submit" value="Login">
    </form>
    </body>
    </html>

    这是处理登录请求的LoginServlet。

    注意我们为响应设置的cookie,然后将其转发到LoginSuccess.jsp,该cookie将在此处用于跟踪会话。 还要注意,cookie超时设置为30分钟。 理想情况下,应该有一个复杂的逻辑来设置cookie值以进行会话跟踪,以使其不会与任何其他请求冲突。

    <%@ page language="java" contentType="text/html; charset=US-ASCII"
        pageEncoding="US-ASCII"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
    <title>Login Success Page</title>
    </head>
    <body>
    <%
    String userName = null;
    Cookie[] cookies = request.getCookies();
    if(cookies !=null){
    for(Cookie cookie : cookies){
    	if(cookie.getName().equals("user")) userName = cookie.getValue();
    }
    }
    if(userName == null) response.sendRedirect("login.html");
    %>
    <h3>Hi <%=userName %>, Login successful.</h3>
    <br>
    <form action="LogoutServlet" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>

    注意,如果我们尝试直接访问JSP,它将把我们转发到登录页面。 当我们单击注销按钮时,我们应确保从客户端浏览器中删除了cookie。

    没有删除Cookie的方法,但是我们可以将最长期限设置为0,以便将其立即从客户端浏览器中删除。

    当我们在上面的应用程序上运行时,我们得到如下图所示的响应。

  3. Session in Java Servlet – HttpSession

    Servlet API provides Session management through HttpSession interface. We can get session from HttpServletRequest object using following methods. HttpSession allows us to set objects as attributes that can be retrieved in future requests.

    1. HttpSession getSession() – This method always returns a HttpSession object. It returns the session object attached with the request, if the request has no session attached, then it creates a new session and return it.
    2. HttpSession getSession(boolean flag) – This method returns HttpSession object if request has session else it returns null.

    Some of the important methods of HttpSession are:

    1. String getId() – Returns a string containing the unique identifier assigned to this session.
    2. Object getAttribute(String name) – Returns the object bound with the specified name in this session, or null if no object is bound under the name. Some other methods to work with Session attributes are getAttributeNames(), removeAttribute(String name) and setAttribute(String name, Object value).
    3. long getCreationTime() – Returns the time when this session was created, measured in milliseconds since midnight January 1, 1970 GMT. We can get last accessed time with getLastAccessedTime() method.
    4. setMaxInactiveInterval(int interval) – Specifies the time, in seconds, between client requests before the servlet container will invalidate this session. We can get session timeout value from getMaxInactiveInterval() method.
    5. ServletContext getServletContext() – Returns ServletContext object for the application.
    6. boolean isNew() – Returns true if the client does not yet know about the session or if the client chooses not to join the session.
    7. void invalidate() – Invalidates this session then unbinds any objects bound to it.

    Understanding JSESSIONID Cookie

    When we use HttpServletRequest getSession() method and it creates a new request, it creates the new HttpSession object and also add a Cookie to the response object with name JSESSIONID and value as session id. This cookie is used to identify the HttpSession object in further requests from client. If the cookies are disabled at client side and we are using URL rewriting then this method uses the jsessionid value from the request URL to find the corresponding session. JSESSIONID cookie is used for session tracking, so we should not use it for our application purposes to avoid any session related issues.

    Let’s see example of session management using HttpSession object. We will create a dynamic web project in Eclipse with servlet context as ServletHttpSessionExample. The project structure will look like below image.

    login.html is same like earlier example and defined as welcome page for the application in web.xml

    LoginServlet servlet will create the session and set attributes that we can use in other resources or in future requests.

    Our LoginSuccess.jsp code is given below.

    <%@ page language="java" contentType="text/html; charset=US-ASCII"
        pageEncoding="US-ASCII"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
    <title>Login Success Page</title>
    </head>
    <body>
    <%
    //allow access only if session exists
    String user = null;
    if(session.getAttribute("user") == null){
    	response.sendRedirect("login.html");
    }else user = (String) session.getAttribute("user");
    String userName = null;
    String sessionID = null;
    Cookie[] cookies = request.getCookies();
    if(cookies !=null){
    for(Cookie cookie : cookies){
    	if(cookie.getName().equals("user")) userName = cookie.getValue();
    	if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue();
    }
    }
    %>
    <h3>Hi <%=userName %>, Login successful. Your Session ID=<%=sessionID %></h3>
    <br>
    User=<%=user %>
    <br>
    <a href="CheckoutPage.jsp">Checkout Page</a>
    <form action="LogoutServlet" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>

    When a JSP resource is used, container automatically creates a session for it, so we can’t check if session is null to make sure if user has come through login page, so we are using session attribute to validate request.

    CheckoutPage.jsp is another page and it’s code is given below.

    Our LogoutServlet code is given below.

    package com.journaldev.servlet.session;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * Servlet implementation class LogoutServlet
     */
    @WebServlet("/LogoutServlet")
    public class LogoutServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	response.setContentType("text/html");
        	Cookie[] cookies = request.getCookies();
        	if(cookies != null){
        	for(Cookie cookie : cookies){
        		if(cookie.getName().equals("JSESSIONID")){
        			System.out.println("JSESSIONID="+cookie.getValue());
        			break;
        		}
        	}
        	}
        	//invalidate the session if exists
        	HttpSession session = request.getSession(false);
        	System.out.println("User="+session.getAttribute("user"));
        	if(session != null){
        		session.invalidate();
        	}
        	response.sendRedirect("login.html");
        }
    
    }

    Notice that I am printing JSESSIONID cookie value in logs, you can check server log where it will be printing the same value as Session Id in LoginSuccess.jsp

    Below images shows the execution of our web application.

    Java Servlet中的会话– HttpSession

    Servlet API通过HttpSession接口提供会话管理。 我们可以使用以下方法从HttpServletRequest对象获取会话。 HttpSession允许我们将对象设置为可以在将来的请求中检索的属性。

    1. HttpSession getSession() –此方法始终返回HttpSession对象。 它返回随请求附加的会话对象,如果请求没有附加的会话,则创建一个新会话并返回它。
    2. HttpSession getSession(boolean flag) –如果请求具有会话,则此方法返回HttpSession对象,否则返回null。

    HttpSession的一些重要方法是:

    1. String getId() –返回包含分配给该会话的唯一标识符的字符串。
    2. Object getAttribute(String name) –返回在此会话中与指定名称绑定的对象,如果该名称下未绑定任何对象,则返回null。 使用Session属性的其他一些方法是getAttributeNames()removeAttribute(String name)setAttribute(String name, Object value)
    3. long getCreationTime() –返回创建此会话的时间,以格林尼治标准时间1970年1月1日午夜以来的毫秒数为单位。 我们可以使用getLastAccessedTime()方法获取上次访问时间。
    4. setMaxInactiveInterval(int interval)–指定客户机请求之间的时间,以秒为单位,此时间间隔表示Servlet容器使该会话无效。 我们可以从getMaxInactiveInterval()方法获取会话超时值。
    5. ServletContext getServletContext() –返回应用程序的ServletContext对象。
    6. boolean isNew() –如果客户端尚不知道会话或客户端选择不加入会话,则返回true。
    7. void invalidate()使此会话无效,然后取消绑定到该会话的任何对象。

    了解JSESSIONID Cookie

    当我们使用HttpServletRequest getSession()方法创建一个新请求时,它会创建一个新的HttpSession对象,并向响应对象添加一个名称为JSESSIONID且值为会话ID的Cookie。 此cookie用于在客户端的其他请求中标识HttpSession对象。 如果在客户端禁用了cookie,并且我们正在使用URL重写,则此方法将使用请求URL中的jsessionid值来查找相应的会话。 JSESSIONID cookie用于会话跟踪,因此我们不应将其用于应用程序目的,以避免任何与会话相关的问题。

    让我们看看使用HttpSession对象进行会话管理的示例。 我们将在Eclipse中创建一个带有ServletHttpSessionExample的servlet上下文的动态Web项目。 项目结构如下图所示。

    login.html与前面的示例相同,并在web.xml中定义为应用程序的欢迎页面

    LoginServlet servlet将创建会话并设置可在其他资源或将来的请求中使用的属性。

    下面是我们的LoginSuccess.jsp代码。

    <%@ page language="java" contentType="text/html; charset=US-ASCII"
        pageEncoding="US-ASCII"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
    <title>Login Success Page</title>
    </head>
    <body>
    <%
    //allow access only if session exists
    String user = null;
    if(session.getAttribute("user") == null){
    	response.sendRedirect("login.html");
    }else user = (String) session.getAttribute("user");
    String userName = null;
    String sessionID = null;
    Cookie[] cookies = request.getCookies();
    if(cookies !=null){
    for(Cookie cookie : cookies){
    	if(cookie.getName().equals("user")) userName = cookie.getValue();
    	if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue();
    }
    }
    %>
    <h3>Hi <%=userName %>, Login successful. Your Session ID=<%=sessionID %></h3>
    <br>
    User=<%=user %>
    <br>
    <a href="CheckoutPage.jsp">Checkout Page</a>
    <form action="LogoutServlet" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>

    使用JSP资源时,容器会自动为其创建一个会话,因此我们无法检查session是否为null来确保用户是否已通过登录页面,因此我们使用session属性来验证请求。

    CheckoutPage.jsp是另一个页面,其代码如下。

    下面是我们的LogoutServlet代码。

    package com.journaldev.servlet.session;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * Servlet implementation class LogoutServlet
     */
    @WebServlet("/LogoutServlet")
    public class LogoutServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	response.setContentType("text/html");
        	Cookie[] cookies = request.getCookies();
        	if(cookies != null){
        	for(Cookie cookie : cookies){
        		if(cookie.getName().equals("JSESSIONID")){
        			System.out.println("JSESSIONID="+cookie.getValue());
        			break;
        		}
        	}
        	}
        	//invalidate the session if exists
        	HttpSession session = request.getSession(false);
        	System.out.println("User="+session.getAttribute("user"));
        	if(session != null){
        		session.invalidate();
        	}
        	response.sendRedirect("login.html");
        }
    
    }

    注意,我正在日志中打印JSESSIONID cookie值,您可以在服务器日志中检查它将与LoginSuccess.jsp中的会话ID值打印相同的值。

    下图显示了我们的Web应用程序的执行。

  4. Java Servlet中的会话管理– URL重写 (Session Management in Java Servlet – URL Rewriting)

    As we saw in last section that we can manage a session with HttpSession but if we disable the cookies in browser, it won’t work because server will not receive the JSESSIONID cookie from client. Servlet API provides support for URL rewriting that we can use to manage session in this case.

    The best part is that from coding point of view, it’s very easy to use and involves one step – encoding the URL. Another good thing with Servlet URL Encoding is that it’s a fallback approach and it kicks in only if browser cookies are disabled.

    We can encode URL with HttpServletResponse encodeURL() method and if we have to redirect the request to another resource and we want to provide session information, we can use encodeRedirectURL() method.

    We will create a similar project like above except that we will use URL rewriting methods to make sure session management works fine even if cookies are disabled in browser.

    ServletSessionURLRewriting project structure in eclipse looks like below image.

    <%@ page language="java" contentType="text/html; charset=US-ASCII"
        pageEncoding="US-ASCII"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
    <title>Login Success Page</title>
    </head>
    <body>
    <%
    //allow access only if session exists
    String user = null;
    if(session.getAttribute("user") == null){
    	response.sendRedirect("login.html");
    }else user = (String) session.getAttribute("user");
    String userName = null;
    String sessionID = null;
    Cookie[] cookies = request.getCookies();
    if(cookies !=null){
    for(Cookie cookie : cookies){
    	if(cookie.getName().equals("user")) userName = cookie.getValue();
    	if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue();
    }
    }else{
    	sessionID = session.getId();
    }
    %>
    <h3>Hi <%=userName %>, Login successful. Your Session ID=<%=sessionID %></h3>
    <br>
    User=<%=user %>
    <br>
    <!-- need to encode all the URLs where we want session information to be passed -->
    <a href="<%=response.encodeURL("CheckoutPage.jsp") %>">Checkout Page</a>
    <form action="<%=response.encodeURL("LogoutServlet") %>" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>
    package com.journaldev.servlet.session;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * Servlet implementation class LogoutServlet
     */
    @WebServlet("/LogoutServlet")
    public class LogoutServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	response.setContentType("text/html");
        	Cookie[] cookies = request.getCookies();
        	if(cookies != null){
        	for(Cookie cookie : cookies){
        		if(cookie.getName().equals("JSESSIONID")){
        			System.out.println("JSESSIONID="+cookie.getValue());
        		}
        		cookie.setMaxAge(0);
        		response.addCookie(cookie);
        	}
        	}
        	//invalidate the session if exists
        	HttpSession session = request.getSession(false);
        	System.out.println("User="+session.getAttribute("user"));
        	if(session != null){
        		session.invalidate();
        	}
        	//no encoding because we have invalidated the session
        	response.sendRedirect("login.html");
        }
    
    }

    When we run this project keeping cookies disabled in the browser, below images shows the response pages, notice the jsessionid in URL of browser address bar. Also notice that on LoginSuccess page, user name is null because browser is not sending the cookie send in the last response.

    If cookies are not disabled, you won’t see jsessionid in the URL because Servlet Session API will use cookies in that case.

    如上一节所述,我们可以使用HttpSession管理会话,但是如果禁用浏览器中的cookie,它将无法正常工作,因为服务器不会从客户端接收JSESSIONID cookie。 Servlet API提供了对URL重写的支持,在这种情况下,我们可以使用它来管理会话。

    从编码的角度来看,最好的部分是,它非常易于使用,并且涉及一个步骤-编码URL。 Servlet URL编码的另一个好处是,它是一种后备方法,只有在禁用浏览器cookie的情况下,它才能启动。

    我们可以使用HttpServletResponse encodeURL()方法对URL进行编码,如果必须将请求重定向到另一个资源,并且想要提供会话信息,则可以使用encodeRedirectURL()方法。

    我们将创建与上述类似的项目,除了使用URL重写方法以确保即使在浏览器中禁用Cookie时,会话管理也能正常工作。

    Eclipse中的ServletSessionURLRewriting项目结构如下图所示。

    <%@ page language="java" contentType="text/html; charset=US-ASCII"
        pageEncoding="US-ASCII"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
    <title>Login Success Page</title>
    </head>
    <body>
    <%
    //allow access only if session exists
    String user = null;
    if(session.getAttribute("user") == null){
    	response.sendRedirect("login.html");
    }else user = (String) session.getAttribute("user");
    String userName = null;
    String sessionID = null;
    Cookie[] cookies = request.getCookies();
    if(cookies !=null){
    for(Cookie cookie : cookies){
    	if(cookie.getName().equals("user")) userName = cookie.getValue();
    	if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue();
    }
    }else{
    	sessionID = session.getId();
    }
    %>
    <h3>Hi <%=userName %>, Login successful. Your Session ID=<%=sessionID %></h3>
    <br>
    User=<%=user %>
    <br>
    <!-- need to encode all the URLs where we want session information to be passed -->
    <a href="<%=response.encodeURL("CheckoutPage.jsp") %>">Checkout Page</a>
    <form action="<%=response.encodeURL("LogoutServlet") %>" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>
    package com.journaldev.servlet.session;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * Servlet implementation class LogoutServlet
     */
    @WebServlet("/LogoutServlet")
    public class LogoutServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	response.setContentType("text/html");
        	Cookie[] cookies = request.getCookies();
        	if(cookies != null){
        	for(Cookie cookie : cookies){
        		if(cookie.getName().equals("JSESSIONID")){
        			System.out.println("JSESSIONID="+cookie.getValue());
        		}
        		cookie.setMaxAge(0);
        		response.addCookie(cookie);
        	}
        	}
        	//invalidate the session if exists
        	HttpSession session = request.getSession(false);
        	System.out.println("User="+session.getAttribute("user"));
        	if(session != null){
        		session.invalidate();
        	}
        	//no encoding because we have invalidated the session
        	response.sendRedirect("login.html");
        }
    
    }

    当我们运行此项目时,在浏览器中禁用cookie时,下图显示了响应页面,请注意浏览器地址栏URL中的jsessionid。 还要注意,在LoginSuccess页面上,用户名为null,因为浏览器未发送上次响应中发送的cookie。

    如果未禁用Cookie,则URL中不会显示jsessionid,因为Servlet会话API在这种情况下将使用Cookie。

Thats all for session management in java servlets, we will look into Servlet Filters and Listeners and Cookies in future articles.

以上就是Java Servlet中会话管理的全部内容,我们将在以后的文章中介绍Servlet过滤器,侦听器和Cookies。

Update: Check out next article in the series Servlet Filter.

更新:查看Servlet Filter系列中的下一篇文章。

下载专案 (Download Projects)

翻译自: https://www.journaldev.com/1907/java-session-management-servlet-httpsession-url-rewriting

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值