Sem JDBC, sem Servlet, sem JSTL, sem Maven. Credenciais hardcoded (para fins didáticos): alice / 123456
tomcat/webapps:tomcat/
└─ webapps/
└─ mini-auth-simples/
├─ index.jsp
├─ login.jsp
├─ restrito.jsp
└─ logout.jsp
http://localhost:8080/mini-auth-simples/index.jsp<%@ page contentType="text/html; charset=UTF-8" %>
<html>
<head><title>Mini Auth Simples</title></head>
<body>
<h2>Bem-vindos</h2>
<p><a href="login.jsp">Login</a></p>
<p><a href="restrito.jsp">Área restrita</a> (precisa estar logado)</p>
</body>
</html>
login.jsp<%@ page contentType="text/html; charset=UTF-8" %>
<%
String erro = null;
// Se veio por POST, tenta autenticar
if ("POST".equalsIgnoreCase(request.getMethod())) {
String user = request.getParameter("username");
String pass = request.getParameter("password");
// >>> CREDENCIAIS DIDÁTICAS <<<
if ("alice".equals(user) && "123456".equals(pass)) {
session.setAttribute("user", user); // cria sessão "logada"
session.setMaxInactiveInterval(15 * 60); // 15 min de inatividade
response.sendRedirect("restrito.jsp");
return;
} else {
erro = "Usuário ou senha inválidos.";
}
}
%>
<html>
<head><title>Login</title></head>
<body>
<h2>Login</h2>
<% if (erro != null) { %>
<p style="color:red;"><%= erro %></p>
<% } %>
<form method="post" action="login.jsp">
<label>Usuário: <input type="text" name="username" required></label><br>
<label>Senha: <input type="password" name="password" required></label><br>
<button type="submit">Entrar</button>
</form>
<p style="margin-top:8px;">Teste: <b>alice</b> / <b>123456</b></p>
<p><a href="index.jsp">Voltar</a></p>
</body>
</html>
restrito.jsp<%@ page contentType="text/html; charset=UTF-8" %>
<%
String user = (String) session.getAttribute("user");
if (user == null) {
response.sendRedirect("login.jsp");
return;
}
%>
<html>
<head><title>Área Restrita</title></head>
<body>
<h2>Área restrita</h2>
<p>Olá, <b><%= user %></b>! Você está logado.</p>
<form action="logout.jsp" method="post">
<button type="submit">Sair</button>
</form>
<p><a href="index.jsp">Início</a></p>
</body>
</html>
logout.jsp<%@ page contentType="text/html; charset=UTF-8" %>
<%
if ("POST".equalsIgnoreCase(request.getMethod())) {
if (session != null) session.invalidate();
}
response.sendRedirect("index.jsp");
%>
mini-auth-simples no webapps/ do Tomcat.http://localhost:8080/mini-auth-simples/.Se usar Tomcat 10+, troquejavax.*porjakarta.*e ajuste as dependências.
(pode trocar por MySQL depois)
mini-auth/
├─ pom.xml
├─ src/main/java/
│ └─ com/exemplo/auth/
│ ├─ model/User.java
│ ├─ dao/UserDAO.java
│ ├─ servlet/LoginServlet.java
│ ├─ servlet/LogoutServlet.java
│ └─ filter/AuthFilter.java
├─ src/main/resources/
│ └─ data.sql
└─ src/main/webapp/
├─ index.jsp
├─ login.jsp
├─ home.jsp
├─ restrito.jsp
└─ WEB-INF/web.xml
pom.xml (dependências)<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.exemplo</groupId>
<artifactId>mini-auth</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<!-- Servlet API (provided pelo Tomcat 9) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- JSTL para JSP -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- H2 Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.224</version>
<scope>runtime</scope>
</dependency>
<!-- BCrypt para senhas (opcional, mas recomendado) -->
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
</dependencies>
<build>
<finalName>mini-auth</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
</plugin>
</plugins>
</build>
</project>
Se usar Tomcat 10+: troque a dependência do Servlet parajakarta.servlet:jakarta.servlet-api:6.0.0e mudejavax.*→jakarta.*no código.
src/main/resources/data.sqlVamos criar a tabela e um usuário com senha 123456 (hash BCrypt).
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id IDENTITY PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(100) NOT NULL,
name VARCHAR(100) NOT NULL
);
-- username: alice / senha: 123456
INSERT INTO users (username, password_hash, name)
VALUES ('alice', '$2a$10$TnXfX2kq1Tq5z7x4wTQhBec0R2v3s2m2m8xvXqZQyq3V2a3s3mKx2', 'Alice Silva');
O hash acima é de123456(gerado por BCrypt). Quer testar outro usuário? Gere com Java ou um site confiável de BCrypt.
User.javapackage com.exemplo.auth.model;
public class User {
private Long id;
private String username;
private String name;
public User(Long id, String username, String name) {
this.id = id;
this.username = username;
this.name = name;
}
public Long getId() { return id; }
public String getUsername() { return username; }
public String getName() { return name; }
}
UserDAO.javapackage com.exemplo.auth.dao;
import com.exemplo.auth.model.User;
import org.mindrot.jbcrypt.BCrypt;
import java.sql.*;
public class UserDAO {
private static final String JDBC_URL = "jdbc:h2:mem:authdb;DB_CLOSE_DELAY=-1";
private static final String JDBC_USER = "sa";
private static final String JDBC_PASS = "";
static {
// Carrega o script data.sql ao iniciar a classe
try (Connection conn = getConnection()) {
String sql = new String(UserDAO.class.getResourceAsStream("/data.sql").readAllBytes());
for (String stmt : sql.split(";")) {
if (!stmt.trim().isEmpty()) {
try (PreparedStatement ps = conn.prepareStatement(stmt)) {
ps.execute();
}
}
}
} catch (Exception e) {
throw new RuntimeException("Erro inicializando H2/data.sql", e);
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASS);
}
public User authenticate(String username, String passwordPlain) {
String q = "SELECT id, username, password_hash, name FROM users WHERE username = ?";
try (Connection c = getConnection();
PreparedStatement ps = c.prepareStatement(q)) {
ps.setString(1, username);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
String hash = rs.getString("password_hash");
if (BCrypt.checkpw(passwordPlain, hash)) {
return new User(rs.getLong("id"), rs.getString("username"), rs.getString("name"));
}
}
}
} catch (SQLException e) {
throw new RuntimeException("Erro ao autenticar", e);
}
return null;
}
}
LoginServlet.javapackage com.exemplo.auth.servlet;
import com.exemplo.auth.dao.UserDAO;
import com.exemplo.auth.model.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String u = req.getParameter("username");
String p = req.getParameter("password");
User user = new UserDAO().authenticate(u, p);
if (user != null) {
HttpSession session = req.getSession(true);
session.setAttribute("user", user);
session.setMaxInactiveInterval(15 * 60); // 15 minutos
resp.sendRedirect(req.getContextPath() + "/restrito");
} else {
req.setAttribute("erro", "Usuário ou senha inválidos.");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
}
LogoutServlet.javapackage com.exemplo.auth.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
HttpSession s = req.getSession(false);
if (s != null) s.invalidate();
resp.sendRedirect(req.getContextPath() + "/");
}
}
AuthFilter.javapackage com.exemplo.auth.filter;
import com.exemplo.auth.model.User;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.*;
import java.io.IOException;
@WebFilter("/restrito/*") // protege tudo sob /restrito/*
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession(false);
User user = (session == null) ? null : (User) session.getAttribute("user");
if (user == null) {
resp.sendRedirect(req.getContextPath() + "/login");
return;
}
chain.doFilter(request, response);
}
}
Observação: aqui estou usando@WebFilter("/restrito/*"). A JSPrestrito.jspficará em/restrito.jspou em/restrito/index.jsp. A forma mais organizada é colocar como /restrito mapeado por um Servlet que encaminha para a JSP. Para simplificar, abaixo protejo via web.xml (opção alternativa) ou ajusto a URL do filtro para/restrito.jsp.
/restrito.jsp, troque para:@WebFilter("/restrito.jsp")
web.xml (rotas & segurança básica)src/main/webapp/WEB-INF/web.xml<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>mini-auth</display-name>
<!-- Força UTF-8 -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Página inicial -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
index.jsp (linka tudo)<%@ page contentType="text/html; charset=UTF-8" %>
<html>
<head><title>Mini Auth</title></head>
<body>
<h2>Bem-vindo ao Mini-Auth</h2>
<p><a href="home.jsp">Home (pública)</a></p>
<p><a href="restrito.jsp">Área restrita</a></p>
<p><a href="login">Login</a></p>
<form action="logout" method="post" style="margin-top:12px;">
<button type="submit">Logout</button>
</form>
</body>
</html>
home.jsp (pública)<%@ page contentType="text/html; charset=UTF-8" %>
<html>
<head><title>Home</title></head>
<body>
<h2>Página pública</h2>
<p>Qualquer pessoa pode acessar.</p>
<p><a href="index.jsp">Voltar</a></p>
</body>
</html>
login.jsp<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head><title>Login</title></head>
<body>
<h2>Login</h2>
<c:if test="${not empty erro}">
<p style="color:red">${erro}</p>
</c:if>
<form method="post" action="login">
<label>Usuário: <input type="text" name="username" required /></label><br/>
<label>Senha: <input type="password" name="password" required /></label><br/>
<button type="submit">Entrar</button>
</form>
<p>Teste com: <b>alice</b> / <b>123456</b></p>
<p><a href="index.jsp">Voltar</a></p>
</body>
</html>
restrito.jsp (conteúdo protegido)<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="com.exemplo.auth.model.User" %>
<%
User user = (User) session.getAttribute("user");
if (user == null) {
response.sendRedirect(request.getContextPath() + "/login");
return;
}
%>
<html>
<head><title>Área Restrita</title></head>
<body>
<h2>Área restrita</h2>
<p>Olá, <b><%= user.getName() %></b> (@<%= user.getUsername() %>)!</p>
<form action="logout" method="post">
<button type="submit">Sair</button>
</form>
<p><a href="index.jsp">Início</a></p>
</body>
</html>
Nota: aqui protegi a página com checagem de sessão na própria JSP (prático). Em projetos reais, prefira centralizar no Filter (já mostramos). Se quiser usar só o Filter, remova a checagem JSP e deixe o@WebFilter("/restrito.jsp")cuidar.
mvn clean packagemini-auth.war em target/tomcat/webapps/http://localhost:8080/mini-auth//restrito.jsp logado e deslogadoresponse e trocar para HTTPS.@WebFilter("/restrito/*").UserDAO com pool (HikariCP)./restrito.jsp redireciona para /login se não logado

// Obtendo ou criando uma sessão
HttpSession session = request.getSession();
// Ou especificando se deve criar caso não exista
HttpSession session = request.getSession(true);

http://meusite.com.br/pagina.jsp;jsessionid=A43F7D2C0EE0B35742B15B41577E5F8A
// Armazenando dados na sessão
session.setAttribute("usuario", usuarioLogado);
session.setAttribute("permissoes", listaPermissoes);
session.setAttribute("tema", temaPreferido);
// Recuperando dados da sessão
Usuario user = (Usuario) session.getAttribute("usuario");
List permissoes = (List) session.getAttribute("permissoes");
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
// Validação simples (substitua por consulta ao banco)
if ("admin".equals(username) && "senha123".equals(password)) {
// Cria a sessão
HttpSession session = request.getSession();
// Armazena informações do usuário
session.setAttribute("usuarioLogado", username);
session.setAttribute("autenticado", true);
// Redireciona para área restrita
response.sendRedirect("areaRestrita.jsp");
} else {
// Redireciona de volta com mensagem de erro
response.sendRedirect("login.jsp?erro=credenciais");
}
}
}
// Define o tempo máximo de inatividade (em segundos)
session.setMaxInactiveInterval(1800); // 30 minutos
// Para sessões mais curtas (ex: área sensível)
session.setMaxInactiveInterval(300); // 5 minutos
// Para sessões mais longas (ex: "Lembrar de mim")
session.setMaxInactiveInterval(86400); // 24 horas

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Obtém a sessão atual (sem criar nova)
HttpSession session = request.getSession(false);
if (session != null) {
// Invalida a sessão
session.invalidate();
}
// Redireciona para a página inicial
response.sendRedirect("index.jsp");
}
}
<%
// Verifica se usuário não está autenticado
if (session.getAttribute("autenticado") == null) {
// Redireciona para página de login
response.sendRedirect("login.jsp");
return; // Importante para interromper a execução
}
%>
<!-- Conteúdo restrito aqui -->

@WebFilter("/admin/*")
public class AutorizacaoFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// Obtém a sessão (sem criar nova)
HttpSession session = req.getSession(false);
// Verifica se está autenticado
boolean isAutenticado = session != null &&
session.getAttribute("autenticado") != null &&
(Boolean) session.getAttribute("autenticado");
// Permite o acesso ou redireciona
if (isAutenticado) {
// Continua o processamento da requisição
chain.doFilter(request, response);
} else {
// Redireciona para login
res.sendRedirect(req.getContextPath() + "/login.jsp");
}
}
// Outros métodos do Filter...
}
<!-- login.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>Acesso ao Sistema</h1>
<% if (request.getParameter("erro") != null) { %>
<p style="color: red;">Usuário ou senha inválidos!</p>
<% } %>
<form action="login" method="post">
<div>
<label for="username">Usuário:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Senha:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Entrar</button>
</form>
</body>
</html>
// No LoginServlet, substitua a validação simples por:
String sql = "SELECT * FROM usuarios WHERE username = ? AND senha = ?";
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, username);
stmt.setString(2, password); // Idealmente, use hash+salt
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
// Usuário encontrado, credenciais válidas
HttpSession session = request.getSession();
session.setAttribute("usuarioLogado", username);
session.setAttribute("autenticado", true);
// Opcional: carregar mais dados do usuário
session.setAttribute("nomeCompleto", rs.getString("nome"));
session.setAttribute("perfil", rs.getString("perfil"));
response.sendRedirect("areaRestrita.jsp");
return;
}
}
}
// Se chegou aqui, credenciais inválidas
response.sendRedirect("login.jsp?erro=credenciais");

import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
// Gerar salt aleatório
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
String saltBase64 = Base64.getEncoder().encodeToString(salt);
// Combinar senha com salt e aplicar hash
String senha = "minhasenha";
String senhaComSalt = senha + saltBase64;
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashedPassword = md.digest(senhaComSalt.getBytes());
String hashedPasswordBase64 = Base64.getEncoder().encodeToString(hashedPassword);
// Armazenar no banco: hashedPasswordBase64 e saltBase64 (em campos separados)
// No LoginServlet, após validar credenciais:
// Invalida a sessão antiga
session.invalidate();
// Cria uma nova sessão
session = request.getSession(true);
// Armazena os dados do usuário na nova sessão
session.setAttribute("usuarioLogado", username);
session.setAttribute("autenticado", true);

<!-- areaRestrita.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Área Restrita</title>
</head>
<body>
<h1>Bem-vindo à Área Restrita</h1>
<p>
Olá, ${sessionScope.usuarioLogado}!
Você está autenticado.
</p>
<div>
<a href="conteudoProtegido.jsp">Conteúdo Protegido</a>
</div>
<div>
<a href="logout">Sair do Sistema</a>
</div>
</body>
</html>


<h3>Informações da Sessão (Debug)</h3>
<p>ID da Sessão: <%= session.getId() %></p>
<p>Criada em: <%= new java.util.Date(session.getCreationTime()) %></p>
<p>Último acesso: <%= new java.util.Date(session.getLastAccessedTime()) %></p>
<p>Tempo máximo inativo: <%= session.getMaxInactiveInterval() %> segundos</p>
<p>Usuário logado: <%= session.getAttribute("usuarioLogado") %></p>
<!-- No login.jsp -->
<%
String mensagem = "";
String tipo = "";
if (request.getParameter("erro") != null) {
String erro = request.getParameter("erro");
if ("credenciais".equals(erro)) {
mensagem = "Usuário ou senha inválidos. Tente novamente.";
tipo = "erro";
} else if ("sessao".equals(erro)) {
mensagem = "Sua sessão expirou por inatividade. Por favor, faça login novamente.";
tipo = "aviso";
} else if ("acesso".equals(erro)) {
mensagem = "Você precisa fazer login para acessar esta página.";
tipo = "info";
} else if ("logout".equals(erro)) {
mensagem = "Você saiu do sistema com sucesso.";
tipo = "sucesso";
}
}
%>
<% if (!mensagem.isEmpty()) { %>
<div class="mensagem <%= tipo %>">
<%= mensagem %>
</div>
<% } %>
// Verificar se usuário tem permissão específica
if (session.getAttribute("perfil") != null &&
"ADMIN".equals(session.getAttribute("perfil"))) {
// Mostrar funcionalidades de administrador
} else {
// Esconder ou desabilitar funcionalidades restritas
}