Поиск по сайту:

Управление сеансом в Java — HttpServlet, файлы cookie, перезапись URL


  1. Руководство по веб-приложениям Java
  2. Учебное пособие по сервлетам Java

Управление сессиями в Java

Эта статья призвана объяснить управление сеансами в сервлетах с использованием различных методов и примеров программ.

Что такое сессия? Управление сеансом в Java — файлы cookie Сеанс в сервлете Java — HttpSession Управление сеансом в сервлете Java — перезапись URL Что такое сессия? Протокол HTTP и веб-серверы не имеют состояния, это означает, что для веб-сервера каждый запрос является новым запросом для обработки, и они не могут определить, исходит ли он от клиента, который ранее отправлял запрос. Но иногда в веб-приложениях мы должны знать, кто является клиентом, и соответствующим образом обрабатывать запрос. Например, приложение корзины покупок должно знать, кто отправляет запрос на добавление товара и в какую корзину этот товар должен быть добавлен, или кто отправляет запрос на оформление заказа, чтобы оно могло списать сумму с правильного клиента. Сеанс — это состояние преобразования между клиентом и сервером, и он может состоять из нескольких запросов и ответов между клиентом и сервером. Поскольку HTTP и веб-сервер не имеют состояния, единственный способ поддерживать сеанс — это когда некоторая уникальная информация о сеансе (идентификатор сеанса) передается между сервером и клиентом в каждом запросе и ответе. Есть несколько способов, с помощью которых мы можем предоставить уникальный идентификатор в запросе и ответе. Аутентификация пользователя. Это очень распространенный способ, когда пользователь может предоставить учетные данные для аутентификации со страницы входа, а затем мы можем передать информацию для аутентификации между сервером и клиентом для поддержания сеанса. Это не очень эффективный метод, потому что он не будет работать, если один и тот же пользователь входит в систему из разных браузеров. Скрытое поле HTML. Мы можем создать уникальное скрытое поле в HTML, и когда пользователь начнет навигацию, мы можем установить его значение, уникальное для пользователя, и отслеживать сеанс. Этот метод нельзя использовать со ссылками, потому что он требует отправки формы каждый раз, когда делается запрос от клиента к серверу со скрытым полем. Также это небезопасно, потому что мы можем получить значение скрытого поля из источника HTML и использовать его для взлома сеанса. Перезапись URL. Мы можем добавить параметр идентификатора сеанса к каждому запросу и ответу, чтобы отслеживать сеанс. Это очень утомительно, потому что нам нужно отслеживать этот параметр в каждом ответе и следить за тем, чтобы он не конфликтовал с другими параметрами. Файлы cookie. Файлы cookie представляют собой небольшой фрагмент информации, который отправляется веб-сервером в заголовке ответа и сохраняется в файлах cookie браузера. Когда клиент делает дополнительный запрос, он добавляет файл cookie в заголовок запроса, и мы можем использовать его для отслеживания сеанса. Мы можем поддерживать сеанс с помощью файлов cookie, но если клиент отключит файлы cookie, он не будет работать. API управления сеансом. API управления сеансом построен на основе вышеперечисленных методов отслеживания сеанса. Некоторые из основных недостатков всех вышеперечисленных методов: В большинстве случаев мы не хотим отслеживать только сеанс, мы должны хранить некоторые данные в сеансе, которые мы можем использовать в будущих запросах. Это потребует больших усилий, если мы попытаемся реализовать это. Все вышеперечисленные способы не являются полными сами по себе, все они не будут работать в том или ином сценарии. Поэтому нам нужно решение, которое может использовать эти методы отслеживания сеансов для обеспечения управления сеансами во всех случаях. Вот почему нам нужен API управления сеансом, а технология сервлетов J2EE поставляется с API управления сеансом, который мы можем использовать.

Управление сеансом в Java — файлы cookie

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ServletCookieExample</display-name>
  <welcome-file-list>
    <welcome-file>login.html</welcome-file>
  </welcome-file-list>
</web-app>

Страница приветствия нашего приложения — 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, который обрабатывает запрос на вход.

package com.journaldev.servlet.session;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
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;

/**
 * Servlet implementation class LoginServlet
 */
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private final String userID = "Pankaj";
	private final String password = "journaldev";

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// get request parameters for userID and password
		String user = request.getParameter("user");
		String pwd = request.getParameter("pwd");
		
		if(userID.equals(user) && password.equals(pwd)){
			Cookie loginCookie = new Cookie("user",user);
			//setting cookie to expiry in 30 mins
			loginCookie.setMaxAge(30*60);
			response.addCookie(loginCookie);
			response.sendRedirect("LoginSuccess.jsp");
		}else{
			RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
			PrintWriter out= response.getWriter();
			out.println("<font color=red>Either user name or password is wrong.</font>");
			rd.include(request, response);
		}

	}

}

Обратите внимание на файл 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 удалены из браузера клиента.

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 loginCookie = null;
    	Cookie[] cookies = request.getCookies();
    	if(cookies != null){
    	for(Cookie cookie : cookies){
    		if(cookie.getName().equals("user")){
    			loginCookie = cookie;
    			break;
    		}
    	}
    	}
    	if(loginCookie != null){
    		loginCookie.setMaxAge(0);
        	response.addCookie(loginCookie);
    	}
    	response.sendRedirect("login.html");
    }

}

Сеанс в сервлете Java — HttpSession

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, если ни один объект не связан с этим именем. Некоторые другие методы работы с атрибутами сеанса: getAttributeNames(), removeAttribute(имя строки) и setAttribute(имя строки, значение объекта).< /li>
  3. long getCreationTime() — возвращает время создания сеанса, измеренное в миллисекундах с полуночи 1 января 1970 года по Гринвичу. Мы можем получить время последнего доступа с помощью метода getLastAccessedTime().
  4. setMaxInactiveInterval(int interval) — указывает время в секундах между клиентскими запросами, прежде чем контейнер сервлетов сделает этот сеанс недействительным. Мы можем получить значение времени ожидания сеанса из метода getMaxInactiveInterval().
  5. ServletContext getServletContext() — возвращает объект ServletContext для приложения.
  6. boolean isNew() — возвращает значение true, если клиент еще не знает о сеансе или если он не хочет присоединяться к сеансу.
  7. void invalidate() — делает этот сеанс недействительным, а затем отвязывает все связанные с ним объекты.

Понимание файла cookie JSESSIONID

package com.journaldev.servlet.session;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
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 LoginServlet
 */
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private final String userID = "admin";
	private final String password = "password";

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// get request parameters for userID and password
		String user = request.getParameter("user");
		String pwd = request.getParameter("pwd");
		
		if(userID.equals(user) && password.equals(pwd)){
			HttpSession session = request.getSession();
			session.setAttribute("user", "Pankaj");
			//setting session to expiry in 30 mins
			session.setMaxInactiveInterval(30*60);
			Cookie userName = new Cookie("user", user);
			userName.setMaxAge(30*60);
			response.addCookie(userName);
			response.sendRedirect("LoginSuccess.jsp");
		}else{
			RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
			PrintWriter out= response.getWriter();
			out.println("<font color=red>Either user name or password is wrong.</font>");
			rd.include(request, response);
		}

	}

}

Наш код 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, контейнер автоматически создает для него сеанс, поэтому мы не можем проверить, является ли сеанс нулевым, чтобы убедиться, что пользователь прошел страницу входа в систему, поэтому мы используем атрибут сеанса для проверки запроса. CheckoutPage.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
if(session.getAttribute("user") == null){
	response.sendRedirect("login.html");
}
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();
}
}
%>
<h3>Hi <%=userName %>, do the checkout.</h3>
<br>
<form action="LogoutServlet" method="post">
<input type="submit" value="Logout" >
</form>
</body>
</html>

Наш код 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");
    }

}

Управление сеансом в сервлете Java — перезапись URL

package com.journaldev.servlet.session;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
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 LoginServlet
 */
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private final String userID = "admin";
	private final String password = "password";

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// get request parameters for userID and password
		String user = request.getParameter("user");
		String pwd = request.getParameter("pwd");
		
		if(userID.equals(user) && password.equals(pwd)){
			HttpSession session = request.getSession();
			session.setAttribute("user", "Pankaj");
			//setting session to expiry in 30 mins
			session.setMaxInactiveInterval(30*60);
			Cookie userName = new Cookie("user", user);
			response.addCookie(userName);
			//Get the encoded URL string
			String encodedURL = response.encodeRedirectURL("LoginSuccess.jsp");
			response.sendRedirect(encodedURL);
		}else{
			RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html");
			PrintWriter out= response.getWriter();
			out.println("<font color=red>Either user name or password is wrong.</font>");
			rd.include(request, response);
		}

	}

}
<%@ 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>
<%@ 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;
//allow access only if session exists
if(session.getAttribute("user") == null){
	response.sendRedirect("login.html");
}else userName = (String) session.getAttribute("user");
String sessionID = null;
Cookie[] cookies = request.getCookies();
if(cookies !=null){
for(Cookie cookie : cookies){
	if(cookie.getName().equals("user")) userName = cookie.getValue();
}
}
%>
<h3>Hi <%=userName %>, do the checkout.</h3>
<br>
<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");
    }

}

Это все, что касается управления сеансом в сервлетах Java, мы рассмотрим фильтры сервлетов, прослушиватели и файлы cookie в следующих статьях. Обновление: ознакомьтесь со следующей статьей из серии Servlet Filter.

Скачать проекты

  • Скачать пример проекта Servlet Cookie
  • Скачать пример проекта HttpSession сервлета
  • Скачать пример проекта перезаписи URL-адреса сеанса сервлета