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. As sessões em Servlets Java são gerenciadas de várias maneiras, como Cookies, API HttpSession, reescrita de URL, etc. Este é o terceiro artigo na 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 Servlet Java

Gerenciamento de Sessão em Java

Este artigo tem como objetivo explicar sobre o gerenciamento de sessões 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 Servlet Java – HttpSession

  4. Gerenciamento de Sessão em Servlet Java – 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 requisição é uma nova requisição a ser processada e eles não conseguem identificar se está vindo de um cliente que enviou requisições anteriormente. Mas às vezes em aplicações web, precisamos saber quem é o cliente e processar a requisição de acordo. Por exemplo, uma aplicação de carrinho de compras deve saber quem está enviando a requisição para adicionar um item e em qual carrinho o item deve ser adicionado, ou quem está enviando a requisição de checkout para que possa cobrar o valor do cliente correto. A sessão é um estado de conversação entre cliente e servidor e pode consistir em várias requisições e respostas entre cliente e servidor. Como tanto o HTTP quanto 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 requisição e resposta. Existem várias maneiras de fornecer um identificador único na requisição e na resposta.

    1. Autenticação de Usuário – Esta é a maneira mais 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 o servidor e o 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 navegadores diferentes.

    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 toda vez que a requisição é 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 do código-fonte HTML e usá-lo para hackear a sessão.

    3. Redefinição de URL – Podemos anexar um parâmetro de identificação de sessão com cada requisição e resposta para acompanhar a sessão. Isso é muito tedioso porque precisamos acompanhar esse parâmetro em todas as respostas 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 uma nova requisição, adiciona o cookie ao cabeçalho da requisição e podemos utilizá-lo para acompanhar a sessão. Podemos manter uma sessão com cookies, mas se o cliente desabilitar os cookies, isso não funcionará.

    5. API de Gerenciamento de Sessão – A API de Gerenciamento de Sessão é construída sobre os métodos acima para rastreamento de sessão. 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 futuras requisições. 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 particular. 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 que precisamos da API de Gerenciamento de Sessão e a tecnologia de Servlet J2EE vem com uma API de gerenciamento de sessão que podemos usar.

  6. html

    Gerenciamento de Sessão em Java – Cookies

    Os cookies são muito utilizados em aplicações web para personalizar a resposta com base em suas escolhas ou para acompanhar a sessão. Antes de avançarmos para a API de Gerenciamento de Sessão do Servlet, gostaria de mostrar como podemos acompanhar a sessão com cookies por meio de uma pequena aplicação web. Criaremos uma aplicação web dinâmica ServletCookieExample com a estrutura do 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 inicial 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.

    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;
    
    /**
     * Implementação do Servlet da Classe Login
     */
    @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 {
    
    		// 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)){
    			Cookie loginCookie = new Cookie("user",user);
    			// definindo 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 depois encaminhando para LoginSuccess.jsp, este cookie será usado lá para rastrear a sessão. Observe também 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, de modo 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 do 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.

    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 Logout
     */
    @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 através 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. Ele retorna o objeto de sessão associado à solicitação. Se a solicitação não tiver uma sessão associada, então cria uma nova sessão e a retorna.
    2. HttpSession getSession(boolean flag) – Este método retorna um objeto HttpSession se a solicitação tiver uma sessão, caso contrário, retorna null.

    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 null 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 do servlet invalide esta sessão. Podemos obter o valor do tempo limite da sessão 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 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 de 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 este 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 nossos propósitos de aplicativo para evitar quaisquer problemas relacionados à sessão. Vamos ver um exemplo de gerenciamento de sessão usando o objeto HttpSession. Vamos criar 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 que o exemplo anterior e definido como página de boas-vindas para a aplicação em web.xml O servlet LoginServlet irá criar a sessão e definir atributos que podemos usar em outros recursos ou em solicitações futuras.

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

    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("user");
    String userName = null;
    String sessionID = null;
    Cookie[] cookies = request.getCookies();

  8. Gerenciamento de Sessão em Java Servlet – 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 Servlet é que é uma abordagem de fallback e só entra em ação se os cookies do navegador estiverem desativados. Podemos codificar a URL com o método encodeURL() de HttpServletResponse e se precisarmos redirecionar a solicitação para outro recurso e quisermos fornecer informações de sessão, podemos usar o método encodeRedirectURL(). Criaremos 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>Oi <%=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 da 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>Oi <%=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("/LogoutServlet")
    public

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

Download dos Projetos

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