Sitzungsverwaltung in Java Servlet-Webanwendungen ist ein sehr interessantes Thema. Sitzung in Java Servlets werden auf verschiedene Weisen verwaltet, wie z.B. Cookies, HttpSession API, URL-Rewriting usw. Dies ist der dritte Artikel in der Reihe von Webanwendungs-Tutorials in Java, vielleicht möchten Sie auch die beiden vorherigen Artikel überprüfen.
Sitzungsverwaltung in Java
In diesem Artikel wird erklärt, wie Sitzungsverwaltung in Servlets mithilfe verschiedener Techniken und mit Beispielprogrammen funktioniert.
- – Was ist eine Sitzung?
– Das HTTP-Protokoll und Webserver sind zustandslos, was bedeutet, dass für den Webserver jede Anfrage eine neue Anfrage zum Verarbeiten ist und er nicht identifizieren kann, ob sie von einem Client stammt, der zuvor Anfragen gesendet hat. Aber manchmal in Webanwendungen sollten wir wissen, wer der Client ist und die Anfrage entsprechend verarbeiten. Zum Beispiel sollte eine Einkaufswagenanwendung wissen, wer die Anfrage zum Hinzufügen eines Artikels sendet und in welchen Wagen der Artikel hinzugefügt werden soll oder wer die Kassenanfrage sendet, damit der Betrag dem richtigen Client berechnet werden kann. Eine Sitzung ist ein konversationeller Zustand zwischen Client und Server und kann aus mehreren Anfragen und Antworten zwischen Client und Server bestehen. Da HTTP und Webserver beide zustandslos sind, ist der einzige Weg, eine Sitzung aufrechtzuerhalten, wenn einige eindeutige Informationen über die Sitzung (Sitzungs-ID) in jeder Anfrage und Antwort zwischen Server und Client übermittelt werden. Es gibt mehrere Möglichkeiten, wie wir einen eindeutigen Bezeichner in Anfrage und Antwort bereitstellen können.
–Benutzerauthentifizierung
– Dies ist die sehr verbreitete Methode, bei der der Benutzer Authentifizierungsanmeldeinformationen von der Anmeldeseite bereitstellen kann und wir dann die Authentifizierungsinformationen zwischen Server und Client übergeben können, um die Sitzung aufrechtzuerhalten. Diese Methode ist nicht sehr effektiv, weil sie nicht funktioniert, wenn derselbe Benutzer von verschiedenen Browsern aus angemeldet ist.
– HTML Hidden Field – Wir können ein eindeutiges verstecktes Feld im HTML erstellen, und wenn der Benutzer mit der Navigation beginnt, können wir seinen Wert eindeutig für den Benutzer festlegen und die Sitzung verfolgen. Diese Methode kann nicht mit Links verwendet werden, weil sie das Formular erfordert, das bei jeder Anfrage vom Client zum Server mit dem versteckten Feld übermittelt werden muss. Außerdem ist es nicht sicher, weil wir den Wert des versteckten Feldes aus dem HTML-Quellcode erhalten und ihn verwenden können, um die Sitzung zu hacken.
– URL-Umschreibung – Wir können jedem Antrag und jeder Antwort einen Sitzungsidentifikatorparameter anhängen, um die Sitzung zu verfolgen. Dies ist sehr mühsam, weil wir diesen Parameter in jeder Antwort verfolgen müssen und sicherstellen müssen, dass er nicht mit anderen Parametern kollidiert.
– Cookies – Cookies sind kleine Informationsstücke, die vom Webserver im Antwortheader gesendet und im Browser-Cookies gespeichert werden. Wenn der Client weitere Anfragen stellt, fügt er das Cookie dem Anforderungsheader hinzu, und wir können es verwenden, um die Sitzung zu verfolgen. Wir können eine Sitzung mit Cookies aufrechterhalten, aber wenn der Client die Cookies deaktiviert, funktioniert dies nicht.
– Sitzungsverwaltungs-API – Die Sitzungsverwaltungs-API basiert auf den oben genannten Methoden zur Sitzungsverfolgung. Einige der Hauptnachteile aller oben genannten Methoden sind:
– Die meiste Zeit möchten wir nicht nur die Sitzung verfolgen, wir müssen einige Daten in die Sitzung speichern, die wir in zukünftigen Anfragen verwenden können. Dies erfordert viel Aufwand, wenn wir dies implementieren wollen.
– Alle oben genannten Methoden sind nicht in sich abgeschlossen, sie funktionieren nicht alle in einem bestimmten Szenario. Daher benötigen wir eine Lösung, die diese Methoden der Sitzungsverfolgung nutzen kann, um eine Sitzungsverwaltung in allen Fällen bereitzustellen.
– Deshalb benötigen wir die Sitzungsverwaltungs-API, und die J2EE-Servlet-Technologie bietet eine Sitzungsverwaltungs-API, die wir verwenden können. -
Sitzungsverwaltung in Java – Cookies
Cookies werden in Webanwendungen häufig verwendet, um die Antwort basierend auf Ihrer Auswahl zu personalisieren oder die Sitzung zu verfolgen. Bevor wir zur Servlet-Sitzungsverwaltungs-API übergehen, möchte ich zeigen, wie wir mit Cookies die Sitzung verfolgen können, indem wir eine kleine Webanwendung erstellen. Wir werden eine dynamische Webanwendung ServletCookieExample mit einem Projektstruktur wie im folgenden Bild erstellen.
Das Bereitstellungsdeskriptor-Web.xml der Webanwendung lautet:
<?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>
Die Startseite unserer Anwendung ist login.html, wo wir die Authentifizierungsdetails vom Benutzer erhalten werden.
<!DOCTYPE html> <html> <head> <meta charset="US-ASCII"> <title>Anmeldeseite</title> </head> <body> <form action="LoginServlet" method="post"> Benutzername: <input type="text" name="user"> <br> Passwort: <input type="password" name="pwd"> <br> <input type="submit" value="Anmelden"> </form> </body> </html>
Hier ist der LoginServlet, der sich um die Anmeldeanforderung kümmert.
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-Implementierungsklasse 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 { // Anforderungsparameter für Benutzer-ID und Passwort abrufen String user = request.getParameter("user"); String pwd = request.getParameter("pwd"); if(userID.equals(user) && password.equals(pwd)){ Cookie loginCookie = new Cookie("user",user); // Cookie auf Ablauf in 30 Minuten setzen 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>Entweder Benutzername oder Passwort ist falsch.</font>"); rd.include(request, response); } } }
Beachten Sie das Cookie, das wir der Antwort hinzufügen und dann an LoginSuccess.jsp weiterleiten. Dieses Cookie wird dort zur Verfolgung der Sitzung verwendet. Beachten Sie auch, dass die Cookie-Zeitüberschreitung auf 30 Minuten festgelegt ist. Idealerweise sollte eine komplexe Logik vorhanden sein, um den Cookie-Wert für die Sitzungsverfolgung festzulegen, damit er nicht mit einer anderen Anforderung kollidiert.
<%@ 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>Anmelden Erfolgreich Seite</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>Hallo <%=userName %>, Anmeldung erfolgreich.</h3> <br> <form action="LogoutServlet" method="post"> <input type="submit" value="Abmelden" > </form> </body> </html>
Beachten Sie, dass wenn wir versuchen, auf die JSP direkt zuzugreifen, wir zur Anmeldeseite weitergeleitet werden. Wenn wir auf die Schaltfläche „Abmelden“ klicken, sollten wir sicherstellen, dass das Cookie aus dem Client-Browser entfernt wird.
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-Implementierungsklasse 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"); } }
Es gibt keine Methode, um das Cookie zu entfernen, aber wir können das maximale Alter auf 0 setzen, damit es sofort aus dem Client-Browser gelöscht wird. Wenn wir die obige Anwendung ausführen, erhalten wir eine Antwort wie in den folgenden Bildern.
-
Sitzung in Java Servlet – HttpSession
Das Servlet-API bietet Sitzungsverwaltung über das
HttpSession
-Interface. Wir können eine Sitzung aus demHttpServletRequest
-Objekt mithilfe der folgenden Methoden erhalten. HttpSession ermöglicht es uns, Objekte als Attribute festzulegen, die in zukünftigen Anfragen abgerufen werden können.- HttpSession getSession() – Diese Methode gibt immer ein HttpSession-Objekt zurück. Sie gibt das mit der Anfrage verbundene Sitzungsobjekt zurück. Wenn der Anfrage keine Sitzung zugeordnet ist, erstellt sie eine neue Sitzung und gibt sie zurück.
- HttpSession getSession(boolean flag) – Diese Methode gibt ein HttpSession-Objekt zurück, wenn die Anfrage eine Sitzung hat, sonst gibt sie null zurück.
Einige wichtige Methoden von HttpSession sind:
- String getId() – Gibt einen String zurück, der den eindeutigen Bezeichner dieser Sitzung enthält.
- Object getAttribute(String name) – Gibt das mit dem angegebenen Namen in dieser Sitzung gebundene Objekt zurück oder null, wenn unter dem Namen kein Objekt gebunden ist. Einige andere Methoden zum Arbeiten mit Sitzungsattributen sind
getAttributeNames()
,removeAttribute(String name)
undsetAttribute(String name, Object value)
. - long getCreationTime() – Gibt die Zeit zurück, zu der diese Sitzung erstellt wurde, gemessen in Millisekunden seit Mitternacht am 1. Januar 1970 GMT. Wir können die zuletzt zugegriffene Zeit mit der Methode
getLastAccessedTime()
abrufen. - setMaxInactiveInterval(int interval) – Legt die Zeit in Sekunden fest, die zwischen Clientanfragen verstreichen sollen, bevor der Servletcontainer diese Sitzung ungültig macht. Wir können den Sitzungs-Timeout-Wert mit der Methode
getMaxInactiveInterval()
abrufen. - ServletContext getServletContext() – Gibt das ServletContext-Objekt für die Anwendung zurück.
- boolean isNew() – Gibt true zurück, wenn der Client die Sitzung noch nicht kennt oder wenn der Client sich entscheidet, nicht an der Sitzung teilzunehmen.
- void invalidate() – Invalidiert diese Sitzung und löst alle daran gebundenen Objekte auf.
Verständnis für das JSESSIONID-Cookie
Wenn wir die Methode
HttpServletRequest getSession()
verwenden und sie eine neue Anforderung erstellt, erstellt sie das neue HttpSession-Objekt und fügt auch ein Cookie mit dem Namen JSESSIONID und dem Wert der Sitzungs-ID zum Antwortobjekt hinzu. Dieses Cookie wird verwendet, um das HttpSession-Objekt in weiteren Anfragen vom Client zu identifizieren. Wenn die Cookies auf der Clientseite deaktiviert sind und wir URL-Umschreibung verwenden, verwendet diese Methode den jsessionid-Wert aus der Anforderungs-URL, um die entsprechende Sitzung zu finden. JSESSIONID-Cookie wird zur Sitzungsverfolgung verwendet, daher sollten wir es nicht für unsere Anwendungszwecke verwenden, um etwaige mit der Sitzung zusammenhängende Probleme zu vermeiden. Lassen Sie uns ein Beispiel für die Sitzungsverwaltung mithilfe des HttpSession-Objekts sehen. Wir werden ein dynamisches Webprojekt in Eclipse mit dem Servletkontext als ServletHttpSessionExample erstellen. Die Projektstruktur wird wie auf dem folgenden Bild aussehen.login.html ist wie im vorherigen Beispiel und als Willkommensseite für die Anwendung in der web.xml definiert. Der LoginServlet-Servlet wird die Sitzung erstellen und Attribute festlegen, die wir in anderen Ressourcen oder in zukünftigen Anfragen verwenden können.
paket 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-Implementierungsklasse für den 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 { // Abrufen der Anforderungsparameter für BenutzerID und Passwort 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"); // Sitzung auf Ablauf in 30 Minuten setzen 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>Entweder Benutzername oder Passwort ist falsch.</font>"); rd.include(request, response); } } }
Unser LoginSuccess.jsp-Code ist unten angegeben.
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 -
Sitzungsverwaltung in Java Servlet – URL-Umschreibung
Wie wir im letzten Abschnitt gesehen haben, können wir eine Sitzung mit HttpSession verwalten, aber wenn wir die Cookies im Browser deaktivieren, funktioniert es nicht, weil der Server das JSESSIONID-Cookie vom Client nicht erhalten wird. Die Servlet-API bietet Unterstützung für URL-Umschreibung, die wir verwenden können, um die Sitzung in diesem Fall zu verwalten. Das Beste daran ist, dass es aus Codierungssicht sehr einfach zu verwenden ist und nur einen Schritt beinhaltet – das Codieren der URL. Ein weiterer Vorteil der Servlet-URL-Codierung ist, dass es sich um einen Rückfallansatz handelt und nur dann aktiviert wird, wenn Browser-Cookies deaktiviert sind. Wir können die URL mit der
encodeURL()
-Methode von HttpServletResponse codieren, und wenn wir die Anforderung zu einer anderen Ressource umleiten und Sitzungsinformationen bereitstellen möchten, können wir die MethodeencodeRedirectURL()
verwenden. Wir erstellen ein ähnliches Projekt wie oben, außer dass wir URL-Umschreibungsmethoden verwenden, um sicherzustellen, dass die Sitzungsverwaltung auch dann funktioniert, wenn Cookies im Browser deaktiviert sind. Die Projektstruktur von ServletSessionURLRewriting in Eclipse sieht wie folgt aus: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-Implementierungsklasse für 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 { // Anforderungsparameter für Benutzer-ID und Passwort erhalten 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"); // Sitzung auf Ablauf in 30 Minuten setzen session.setMaxInactiveInterval(30*60); Cookie userName = new Cookie("user", user); response.addCookie(userName); // Die codierte URL-Zeichenfolge abrufen 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>Entweder Benutzername oder Passwort ist falsch.</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>Anmeldeseite erfolgreich</title> </head> <body> <% // Zugriff nur zulassen, wenn die Sitzung existiert 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>Hallo <%=userName %>, Anmeldung erfolgreich. Ihre Sitzungs-ID=<%=sessionID %></h3> <br> Benutzer=<%=user %> <br> <!-- Alle URLs codieren, an denen Sitzungsinformationen übergeben werden sollen --> <a href="<%=response.encodeURL("CheckoutPage.jsp") %>">Checkout-Seite</a> <form action="<%=response.encodeURL("LogoutServlet") %>" method="post"> <input type="submit" value="Abmelden" > </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>Anmeldeseite erfolgreich</title> </head> <body> <% String userName = null; // Zugriff nur zulassen, wenn die Sitzung existiert 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>Hallo <%=userName %>, führen Sie den Checkout durch.</h3> <br> <form action="<%=response.encodeURL("LogoutServlet") %>" method="post"> <input type="submit" value="Abmelden" > </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
Das war’s für die Sitzungsverwaltung in Java-Servlets, wir werden in zukünftigen Artikeln Servlet-Filter und -Listener sowie Cookies untersuchen. Update: Schauen Sie sich den nächsten Artikel in der Serie an Servlet Filter.