Gerenciamento de sessão em Java – HttpServlet, Cookies, Reescrita de URL

Gerenciamento de Sessão em Aplicações Web Servlet Java é um tópico muito interessante. Sessões em Java Servlet são gerenciadas de diferentes formas, como Cookies, API de HttpSession, reescrita de URL, etc. Este é o terceiro artigo da série de tutoriais de Aplicações Web em Java; você pode querer verificar os dois artigos anteriores também.

  1. Tutorial de Aplicação Web Java
  2. Tutorial de Servlet Java

Gerenciamento de Sessão em Java

Este artigo tem como objetivo explicar sobre o gerenciamento de sessão em servlets usando diferentes técnicas e exemplos de programas.

  1. O que é uma Sessão?

  2. Gerenciamento de Sessão em Java – Cookies

  3. Sessão em Java Servlet – HttpSession

  4. Gerenciamento de Sessão em Java Servlet – Reescrita de URL

  5. O que é uma sessão?

    O protocolo HTTP e os servidores web são stateless, o que significa que para o servidor web cada solicitação é uma nova solicitação a ser processada e eles não podem identificar se está vindo de um cliente que enviou solicitações anteriormente. Mas às vezes, em aplicações web, devemos saber quem é o cliente e processar a solicitação de acordo. Por exemplo, uma aplicação de carrinho de compras deve saber quem está enviando a solicitação para adicionar um item e em qual carrinho o item deve ser adicionado, ou quem está enviando a solicitação de checkout para que possa cobrar o valor ao cliente correto. A sessão é um estado conversacional entre cliente e servidor e pode consistir em várias solicitações e respostas entre cliente e servidor. Como o HTTP e o servidor web são stateless, a única maneira de manter uma sessão é quando alguma informação única sobre a sessão (ID da sessão) é passada entre servidor e cliente em cada solicitação e resposta. Existem várias maneiras de fornecer um identificador único na solicitação e resposta.

    1. Autenticação do usuário – Esta é a maneira muito comum em que o usuário pode fornecer credenciais de autenticação na página de login e então podemos passar as informações de autenticação entre servidor e cliente para manter a sessão. Este método não é muito eficaz porque não funcionará se o mesmo usuário estiver logado em diferentes navegadores.

    2. Campo oculto HTML – Podemos criar um campo oculto único no HTML e quando o usuário começa a navegar, podemos definir seu valor único para o usuário e acompanhar a sessão. Este método não pode ser usado com links porque precisa que o formulário seja enviado sempre que a solicitação for feita do cliente para o servidor com o campo oculto. Além disso, não é seguro porque podemos obter o valor do campo oculto a partir da fonte HTML e usá-lo para hackear a sessão.

    3. Rewrite de URL – Podemos anexar um parâmetro de identificação de sessão com cada solicitação e resposta para acompanhar a sessão. Isso é muito tedioso porque precisamos acompanhar este parâmetro em cada resposta e garantir que não esteja entrando em conflito com outros parâmetros.

    4. Cookies – Cookies são pequenas informações enviadas pelo servidor web no cabeçalho da resposta e são armazenadas nos cookies do navegador. Quando o cliente faz novas solicitações, ele adiciona o cookie ao cabeçalho da solicitação e podemos utilizá-lo para acompanhar a sessão. Podemos manter uma sessão com cookies, mas se o cliente desativar os cookies, isso não funcionará.

    5. API de gerenciamento de sessões – A API de gerenciamento de sessões é construída com base nos métodos acima para rastreamento de sessões. Algumas das principais desvantagens de todos os métodos acima são:

      • Muitas vezes, não queremos apenas rastrear a sessão, precisamos armazenar alguns dados na sessão que podemos usar em solicitações futuras. Isso exigirá muito esforço se tentarmos implementar isso.
      • Todos os métodos acima não são completos por si só, todos eles não funcionarão em um cenário específico. Portanto, precisamos de uma solução que possa utilizar esses métodos de rastreamento de sessão para fornecer gerenciamento de sessão em todos os casos.

      Por isso, precisamos da API de gerenciamento de sessões e a tecnologia Servlet J2EE vem com uma API de gerenciamento de sessões que podemos usar.

  6. Gerenciamento de Sessão em Java – Cookies

    Os cookies são muito usados em aplicações web para personalizar a resposta com base em suas escolhas ou para manter o controle da sessão. Antes de avançar para a API de Gerenciamento de Sessão do Servlet, gostaria de mostrar como podemos manter o controle da sessão com cookies através de uma pequena aplicação web. Vamos criar uma aplicação web dinâmica ServletCookieExample com uma estrutura de projeto como na imagem abaixo. O descritor de implantação web.xml da aplicação web é:

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

    A página de boas-vindas de nossa aplicação é login.html, onde obteremos os detalhes de autenticação do usuário.

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="US-ASCII">
    <title>Página de Login</title>
    </head>
    <body>
    
    <form action="LoginServlet" method="post">
    
    Nome de usuário: <input type="text" name="user">
    <br>
    Senha: <input type="password" name="pwd">
    <br>
    <input type="submit" value="Login">
    </form>
    </body>
    </html>
    

    Aqui está o LoginServlet que cuida da solicitação de login.

    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;
    
    /**
     * Implementação do Servlet 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 {
    
    		// obtendo parâmetros da solicitação para usuário e senha
    		String user = request.getParameter("user");
    		String pwd = request.getParameter("pwd");
    		
    		if(userID.equals(user) && password.equals(pwd)){
    			Cookie loginCookie = new Cookie("user",user);
    			// definindo o cookie para expirar em 30 minutos
    			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>Nome de usuário ou senha incorretos.</font>");
    			rd.include(request, response);
    		}
    
    	}
    
    }
    

    Observe o cookie que estamos definindo na resposta e então encaminhando para LoginSuccess.jsp, este cookie será usado lá para rastrear a sessão. Também observe que o tempo limite do cookie é definido para 30 minutos. Idealmente, deveria haver uma lógica complexa para definir o valor do cookie para rastreamento de sessão para que não entre em conflito com qualquer outra solicitação.

    <%@ 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>Página de Sucesso de Login</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>Olá <%=userName %>, Login bem-sucedido.</h3>
    <br>
    <form action="LogoutServlet" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>
    

    Observe que se tentarmos acessar o JSP diretamente, seremos encaminhados para a página de login. Quando clicarmos no botão de Logout, devemos garantir que o cookie seja removido do navegador do cliente.

    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;
    
    /**
     * Implementação do Servlet 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");
        }
    
    }
    

    N

  7. Sessão em Java Servlet – HttpSession

    A API Servlet fornece gerenciamento de sessão por meio da interface HttpSession. Podemos obter a sessão a partir do objeto HttpServletRequest usando os seguintes métodos. HttpSession nos permite definir objetos como atributos que podem ser recuperados em solicitações futuras.

    1. HttpSession getSession() – Este método sempre retorna um objeto HttpSession. Retorna o objeto de sessão anexado à solicitação, se a solicitação não tiver uma sessão anexada, então cria uma nova sessão e a retorna.
    2. HttpSession getSession(boolean flag) – Este método retorna o objeto HttpSession se a solicitação tiver sessão, caso contrário, retorna nulo.

    Alguns dos métodos importantes de HttpSession são:

    1. String getId() – Retorna uma string contendo o identificador único atribuído a esta sessão.
    2. Object getAttribute(String name) – Retorna o objeto vinculado ao nome especificado nesta sessão, ou nulo se nenhum objeto estiver vinculado ao nome. Alguns outros métodos para trabalhar com atributos de sessão são getAttributeNames(), removeAttribute(String name) e setAttribute(String name, Object value).
    3. long getCreationTime() – Retorna o momento em que esta sessão foi criada, medido em milissegundos desde a meia-noite de 1 de janeiro de 1970 GMT. Podemos obter o último tempo de acesso com o método getLastAccessedTime().
    4. setMaxInactiveInterval(int interval) – Especifica o tempo, em segundos, entre as solicitações do cliente antes que o contêiner Servlet invalide esta sessão. Podemos obter o valor de expiração da sessão a a partir do método getMaxInactiveInterval().
    5. ServletContext getServletContext() – Retorna o objeto ServletContext para a aplicação.
    6. boolean isNew() – Retorna true se o cliente ainda não conhecer a sessão ou se o cliente optar por não participar da sessão.
    7. void invalidate() – Invalida esta sessão e, em seguida, desvincula quaisquer objetos vinculados a ela.

    Ao usarmos o método HttpServletRequest getSession() e ele cria uma nova solicitação, ele cria o novo objeto HttpSession e também adiciona um Cookie ao objeto de resposta com o nome JSESSIONID e o valor como ID da sessão. Esse cookie é usado para identificar o objeto HttpSession em solicitações futuras do cliente. Se os cookies estiverem desativados no lado do cliente e estivermos usando a reescrita de URL, então esse método usa o valor jsessionid da URL da solicitação para encontrar a sessão correspondente. O cookie JSESSIONID é usado para rastreamento de sessão, então não devemos usá-lo para os propósitos de nossa aplicação para evitar quaisquer problemas relacionados à sessão. Vamos ver um exemplo de gerenciamento de sessão usando o objeto HttpSession. Criaremos um projeto web dinâmico no Eclipse com o contexto do servlet como ServletHttpSessionExample. A estrutura do projeto será semelhante à imagem abaixo. login.html é o mesmo do exemplo anterior e definido como página de boas-vindas para a aplicação em web.xml O servlet LoginServlet criará a sessão e definirá atributos que podemos usar em outros recursos ou em solicitações futuras.

    pacote 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;
    
    /**
     * Implementação do Servlet do Login
     */
    @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 {
    
    		// obter parâmetros da solicitação para userID e senha
    		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");
    			//definindo sessão para expirar em 30 minutos
    			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>Nome de usuário ou senha incorretos.</font>");
    			rd.include(request, response);
    		}
    
    	}
    
    }
    

    Nosso código LoginSuccess.jsp é dado abaixo.

    <%@ 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>Página de Sucesso no Login</title>
    </head>
    <body>
    <%
    //permitir acesso apenas se a sessão existir
    String user = null;
    if(session.getAttribute("user") == null){
    response.sendRedirect("login.html");
    }else user = (String) session.getAttribute("

  8. Gerenciamento de Sessão em Servlet Java – Reescrita de URL

    Como vimos na última seção, podemos gerenciar uma sessão com HttpSession, mas se desativarmos os cookies no navegador, não funcionará porque o servidor não receberá o cookie JSESSIONID do cliente. A API Servlet fornece suporte para reescrita de URL que podemos usar para gerenciar a sessão nesse caso. A melhor parte é que, do ponto de vista da codificação, é muito fácil de usar e envolve apenas um passo – codificar a URL. Outra coisa boa com a codificação de URL do Servlet é que é uma abordagem de fallback e entra em ação apenas se os cookies do navegador estiverem desativados. Podemos codificar a URL com o método HttpServletResponse encodeURL() e se precisarmos redirecionar a solicitação para outro recurso e quisermos fornecer informações de sessão, podemos usar o método encodeRedirectURL(). Vamos criar um projeto semelhante ao acima, exceto que usaremos métodos de reescrita de URL para garantir que o gerenciamento de sessão funcione corretamente mesmo se os cookies estiverem desativados no navegador. A estrutura do projeto ServletSessionURLRewriting no eclipse parece com a imagem abaixo.

    pacote 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;
    
    /**
     * Implementação do Servlet da classe 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 {
    
    		// obter parâmetros de solicitação para userID e senha
    		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");
    			// definindo a sessão para expirar em 30 minutos
    			session.setMaxInactiveInterval(30*60);
    			Cookie userName = new Cookie("user", user);
    			response.addCookie(userName);
    			// Obter a string de URL codificada
    			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>Nome de usuário ou senha incorretos.</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>Página de Sucesso no Login</title>
    </head>
    <body>
    <%
    //permitir acesso apenas se a sessão existir
    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>Olá <%=userName %>, login bem-sucedido. Seu ID de Sessão=<%=sessionID %></h3>
    <br>
    Usuário=<%=user %>
    <br>
    <!-- precisamos codificar todas as URLs onde queremos que as informações de sessão sejam passadas -->
    <a href="<%=response.encodeURL("CheckoutPage.jsp") %>">Página de Checkout</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>Página de Sucesso no Login</title>
    </head>
    <body>
    <%
    String userName = null;
    //permitir acesso apenas se a sessão existir
    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>Olá <%=userName %>, faça o checkout.</h3>
    <br>
    <form action="<%=response.encodeURL("LogoutServlet") %>" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>
    

    pacote 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;

    /**
    * Implementação do Servlet da classe LogoutServlet
    */
    @WebServlet("/Logout

Isso é tudo para o gerenciamento de sessão em servlets Java, vamos analisar Filtros de Servlet e Ouvintes e Cookies em artigos futuros. Atualização: Confira o próximo artigo da série Filtro de Servlet.

Baixar Projetos

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