Sessiebeheer in Java – HttpServlet, Cookies, URL Herschrijven

Sessiebeheer in Java Servlet-webapplicaties is een zeer interessant onderwerp. Sessie in Java Servlets worden beheerd via verschillende methoden, zoals Cookies, de HttpSession API, URL-rewriting, enzovoort. Dit is het derde artikel in de serie Webapplicatietutorials in Java, je wilt misschien ook de eerdere twee artikelen bekijken.

  1. Java Webapplicatietutorial
  2. Java Servlettutorial

Sessiebeheer in Java

Dit artikel is bedoeld om sessiebeheer in servlets uit te leggen met behulp van verschillende technieken en voorbeeldprogramma’s.

  1. Wat is een sessie?

  2. Sessiebeheer in Java – Cookies

  3. Sessie in Java Servlet – HttpSession

  4. Sessiebeheer in Java Servlet – URL-omleiding

  5. Wat is een Sessie?

    HTTP-protocol en webservers zijn stateless, wat betekent dat voor de webserver elke aanvraag een nieuwe aanvraag is om te verwerken en ze niet kunnen identificeren of deze afkomstig is van een cliënt die eerder aanvragen heeft verzonden. Maar soms moeten we in webtoepassingen weten wie de cliënt is en de aanvraag dienovereenkomstig verwerken. Bijvoorbeeld, een winkelwagen-toepassing moet weten wie de aanvraag verzendt om een item toe te voegen en in welke winkelwagen het item moet worden toegevoegd, of wie de afrekeningsaanvraag verzendt, zodat het het bedrag aan de juiste cliënt kan berekenen. Een sessie is een conversatiestatus tussen client en server en kan bestaan uit meerdere verzoeken en antwoorden tussen client en server. Aangezien zowel HTTP als de webserver stateless zijn, is de enige manier om een sessie te behouden wanneer er unieke informatie over de sessie (sessie-id) wordt doorgegeven tussen server en client in elk verzoek en antwoord. Er zijn verschillende manieren waarop we een unieke identifier kunnen verstrekken in verzoek en antwoord.

    1. Gebruikersverificatie – Dit is de meest voorkomende manier waarop een gebruiker verificatiegegevens van de inlogpagina kan verstrekken en vervolgens kunnen we de verificatiegegevens tussen server en client doorgeven om de sessie te behouden. Dit is geen zeer effectieve methode omdat het niet werkt als dezelfde gebruiker is ingelogd vanuit verschillende browsers.

    2. HTML Verborgen Veld – We kunnen een uniek verborgen veld in de HTML maken en wanneer de gebruiker begint te navigeren, kunnen we de waarde ervan uniek maken voor de gebruiker en de sessie bijhouden. Deze methode kan niet worden gebruikt met links omdat het formulier telkens moet worden ingediend wanneer er van client naar server wordt aangevraagd met het verborgen veld. Bovendien is het niet veilig omdat we de waarde van het verborgen veld uit de HTML-bron kunnen halen en deze kunnen gebruiken om de sessie te hacken.

    3. URL Herschrijven – We kunnen een sessie-identificatieparameter toevoegen aan elk verzoek en antwoord om de sessie bij te houden. Dit is erg tijdrovend omdat we deze parameter in elk antwoord moeten bijhouden en ervoor moeten zorgen dat deze niet in conflict komt met andere parameters.

    4. Cookies – Cookies zijn kleine informatiefragmenten die door de webserver in de responsheader worden verzonden en worden opgeslagen in de browsercookies. Wanneer de client verdere verzoeken doet, voegt het de cookie toe aan de verzoekheader en kunnen we deze gebruiken om de sessie bij te houden. We kunnen een sessie onderhouden met cookies, maar als de client de cookies uitschakelt, werkt het niet.

    5. Sessiebeheer API – Sessiebeheer API is gebouwd op basis van bovenstaande methoden voor sessietracking. Enkele van de belangrijkste nadelen van al deze methoden zijn:

      • Meestal willen we niet alleen de sessie volgen, we moeten wat gegevens opslaan in de sessie die we in toekomstige verzoeken kunnen gebruiken. Dit vereist veel moeite als we proberen dit te implementeren.
      • Alle bovenstaande methoden zijn op zichzelf niet compleet, ze werken allemaal niet in een bepaald scenario. Daarom hebben we een oplossing nodig die deze methoden voor sessietracking kan gebruiken om sessiebeheer in alle gevallen te bieden.

      Daarom hebben we Sessiebeheer API nodig en J2EE Servlet-technologie wordt geleverd met sessiebeheer API die we kunnen gebruiken.

  6. Sessiebeheer in Java – Cookies

    Cookies worden veel gebruikt in webapplicaties om de respons te personaliseren op basis van uw keuze of om de sessie bij te houden. Voordat we verder gaan met de Servlet Session Management API, wil ik laten zien hoe we sessies kunnen bijhouden met cookies via een kleine webapplicatie. We zullen een dynamische webapplicatie ServletCookieExample maken met een projectstructuur zoals de onderstaande afbeelding. Het implementatiebestand web.xml van de webapplicatie is:

    <?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>
    

    De startpagina van onze applicatie is login.html waar we de authenticatiegegevens van de gebruiker zullen verkrijgen.

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

    Hier is de LoginServlet die de inlogaanvraag afhandelt.

    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 implementatieklasse voor 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 {
    
    		// Verkrijg de verzoekparameters voor gebruikers-ID en wachtwoord
    		String user = request.getParameter("user");
    		String pwd = request.getParameter("pwd");
    		
    		if(userID.equals(user) && password.equals(pwd)){
    			Cookie loginCookie = new Cookie("user",user);
    			// stel cookie in op verlopen na 30 minuten
    			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>Ofwel de gebruikersnaam of het wachtwoord is onjuist.</font>");
    			rd.include(request, response);
    		}
    
    	}
    
    }
    

    Let op de cookie die we instellen voor de respons en vervolgens doorsturen naar LoginSuccess.jsp, deze cookie zal daar worden gebruikt om de sessie bij te houden. Let ook op dat de time-out van de cookie is ingesteld op 30 minuten. Idealiter zou er een complexe logica moeten zijn om de cookie-waarde voor sessietracking in te stellen, zodat deze niet botst met een andere aanvraag.

    <%@ 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>Inlogsuccespagina</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 %>, Inloggen succesvol.</h3>
    <br>
    <form action="LogoutServlet" method="post">
    <input type="submit" value="Uitloggen" >
    </form>
    </body>
    </html>
    

    Let op dat als we proberen direct toegang te krijgen tot de JSP, we worden doorgestuurd naar de inlogpagina. Wanneer we op de Uitloggen-knop klikken, moeten we ervoor zorgen dat de cookie wordt verwijderd uit de browser van de client.

    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 implementatieklasse voor 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.setMax

  7. Sessie in Java Servlet – HttpSession

    Servlet API biedt sessiebeheer via de HttpSession-interface. We kunnen een sessie verkrijgen vanuit het HttpServletRequest-object met behulp van de volgende methoden. HttpSession stelt ons in staat om objecten als attributen in te stellen die kunnen worden opgehaald in toekomstige verzoeken.

    1. HttpSession getSession() – Deze methode geeft altijd een HttpSession-object terug. Het retourneert het sessieobject dat is gekoppeld aan het verzoek. Als het verzoek geen sessie heeft, wordt er een nieuwe sessie gemaakt en geretourneerd.
    2. HttpSession getSession(boolean flag) – Deze methode retourneert een HttpSession-object als het verzoek een sessie heeft, anders retourneert het null.

    Enkele van de belangrijke methoden van HttpSession zijn:

    1. String getId() – Geeft een string terug met de unieke identificatie die aan deze sessie is toegewezen.
    2. Object getAttribute(String name) – Geeft het object terug dat is gebonden aan de opgegeven naam in deze sessie, of null als er geen object is gebonden onder die naam. Enkele andere methoden om met sessie-attributen te werken zijn getAttributeNames(), removeAttribute(String name) en setAttribute(String name, Object value).
    3. long getCreationTime() – Geeft de tijd terug waarop deze sessie is gemaakt, gemeten in milliseconden sinds middernacht 1 januari 1970 GMT. We kunnen de laatste toegangstijd krijgen met de methode getLastAccessedTime().
    4. setMaxInactiveInterval(int interval) – Specificeert de tijd, in seconden, tussen clientverzoeken voordat de servletcontainer deze sessie ongeldig maakt. We kunnen de sessietime-outwaarde krijgen van de methode getMaxInactiveInterval().
    5. ServletContext getServletContext() – Geeft het ServletContext-object terug voor de toepassing.
    6. boolean isNew() – Geeft true terug als de client nog niet op de hoogte is van de sessie of als de client ervoor kiest om niet deel te nemen aan de sessie.
    7. void invalidate() – Maakt deze sessie ongeldig en maakt vervolgens alle aan deze gebonden objecten ongedaan.

    Wanneer we de methode HttpServletRequest getSession() gebruiken en deze een nieuw verzoek maakt, maakt het een nieuw HttpSession-object en voegt het ook een cookie toe aan het responsobject met de naam JSESSIONID en de waarde als sessie-id. Deze cookie wordt gebruikt om het HttpSession-object te identificeren in verdere verzoeken van de client. Als de cookies zijn uitgeschakeld aan de kant van de client en we URL-rewriting gebruiken, gebruikt deze methode de jsessionid-waarde uit de verzoek-URL om de overeenkomstige sessie te vinden. JSESSIONID-cookie wordt gebruikt voor sessietracking, dus we moeten het niet gebruiken voor onze toepassingsdoeleinden om eventuele sessiegerelateerde problemen te voorkomen. Laten we een voorbeeld bekijken van sessiebeheer met behulp van HttpSession-object. We maken een dynamisch webproject in Eclipse met de servletcontext als ServletHttpSessionExample. De projectstructuur ziet er als volgt uit. login.html is hetzelfde als in het eerdere voorbeeld en is gedefinieerd als welkomstpagina voor de toepassing in web.xml. De LoginServlet-servlet zal de sessie maken en attributen instellen die we kunnen gebruiken in andere resources of in toekomstige verzoeken.

    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);
    		}
    
    	}
    
    }
    

    Onze LoginSuccess.jsp-code is hieronder gegeven.

    <%@ 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&gt

  8. Sessiebeheer in Java Servlet – URL-herschrijving

    Zoals we hebben gezien in de laatste sectie kunnen we een sessie beheren met HttpSession, maar als we de cookies in de browser uitschakelen, werkt het niet omdat de server de JSESSIONID-cookie niet van de client ontvangt. De Servlet API biedt ondersteuning voor URL-herschrijving die we kunnen gebruiken om de sessie in dit geval te beheren. Het beste is dat vanuit het coderingsstandpunt, het erg gemakkelijk te gebruiken is en slechts één stap vereist – het coderen van de URL. Een ander goed ding van Servlet URL Encoding is dat het een fallback-benadering is en alleen wordt gebruikt als de browsercookies zijn uitgeschakeld. We kunnen URL coderen met de HttpServletResponse encodeURL()-methode en als we het verzoek naar een andere bron willen omleiden en sessie-informatie willen verstrekken, kunnen we de methode encodeRedirectURL() gebruiken. We zullen een vergelijkbaar project maken als hierboven, behalve dat we URL-herschrijvingsmethoden zullen gebruiken om ervoor te zorgen dat sessiebeheer goed werkt, zelfs als cookies zijn uitgeschakeld in de browser. De projectstructuur van ServletSessionURLRewriting in Eclipse ziet eruit als de onderstaande afbeelding.

    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-implementatieklasse 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 {
    
            // requestparameters ophalen voor gebruikers-ID en wachtwoord
            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");
                // sessie instellen op verlopen in 30 minuten
                session.setMaxInactiveInterval(30*60);
                Cookie userName = new Cookie("user", user);
                response.addCookie(userName);
                // De gecodeerde URL-string ophalen
                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>Ofwel gebruikersnaam of wachtwoord is verkeerd.</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>Inlogsuccespagina</title>
    </head>
    <body>
    <%
    // toegang alleen toestaan als sessie bestaat
    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 %>, inloggen gelukt. Uw sessie-ID=<%=sessionID %></h3>
    <br>
    Gebruiker=<%=user %>
    <br>
    <!-- alle URL's coderen waar we sessie-informatie willen doorgeven -->
    <a href="<%=response.encodeURL("CheckoutPage.jsp") %>">Afrekenpagina</a>
    <form action="<%=response.encodeURL("LogoutServlet") %>" method="post">
    <input type="submit" value="Uitloggen" >
    </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>Inlogsuccespagina</title>
    </head>
    <body>
    <%
    String userName = null;
    // toegang alleen toestaan als sessie bestaat
    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 %>, doe de checkout.</h3>
    <br>
    <form action="<%=response.encodeURL("LogoutServlet") %>" method="post">
    <input type="submit" value="Uitloggen" >
    </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;

Dat is alles voor sessiebeheer in Java Servlets, we zullen in toekomstige artikelen Servlet Filters en Listeners en Cookies onderzoeken. Update: Bekijk het volgende artikel in de serie Servlet Filter.

Projecten downloaden

Source:
https://www.digitalocean.com/community/tutorials/java-session-management-servlet-httpsession-url-rewriting