Implementação de um Sistema de Autenticação com Java Servlets e JDBC

O desenvolvimento de um sistema de login robusto em aplicações Java Web envolve a segregação de responsabilidades entre as camadas de persistência, lógica de negócio e controle. Abaixo, detalhamos o fluxo de implementação de um mecanismo de autenticação utilizando o padrão MVC clássico.

1. Camada de Acesso a Dados (DAO)

A primeira etapa consiste em criar um método capaz de extrair as informações do usuário do banco de dados com base em um identificador único. Esta camada interage diretamente com o banco através de JDBC.


public User findUserByIdentifier(Connection conn, String loginName) throws SQLException {
    PreparedStatement stmt = null;
    ResultSet resultSet = null;
    User account = null;

    if (conn != null) {
        String query = "SELECT * FROM sys_user WHERE login_id = ?";
        stmt = conn.prepareStatement(query);
        stmt.setString(1, loginName);
        resultSet = stmt.executeQuery();

        if (resultSet.next()) {
            account = new User();
            account.setInternalId(resultSet.getInt("id"));
            account.setLoginId(resultSet.getString("login_id"));
            account.setFullName(resultSet.getString("full_name"));
            account.setHashedPassword(resultSet.getString("password_hash"));
            account.setRoleLevel(resultSet.getInt("role_id"));
            // Atribuição de outros campos necessários...
        }
        // Fechamento seletivo de recursos para manter a conexão ativa para a Service
        if (stmt != null) stmt.close();
        if (resultSet != null) resultSet.close();
    }
    return account;
}

2. Camada de Lógica de Negócio (Service)

A classe de serviço gerencia a transação e valida se as credenciais fornecidas pelo usuário coincidem com os dados armazenados.


public class AccountService {
    private UserDAO persistenceLayer = new UserDAOImpl();

    public User authenticate(String loginId, String plainPassword) {
        Connection dbConn = null;
        User activeUser = null;

        try {
            dbConn = DatabaseUtility.getConnection();
            activeUser = persistenceLayer.findUserByIdentifier(dbConn, loginId);
        } catch (Exception error) {
            error.printStackTrace();
        } finally {
            DatabaseUtility.releaseResources(dbConn, null, null);
        }

        // Validação da senha
        if (activeUser != null && !activeUser.getHashedPassword().equals(plainPassword)) {
            activeUser = null;
        }

        return activeUser;
    }
}

3. Controlador de Autenticação (Servlet)

O Servlet atua como o orquestrador, recebendo a requisição HTTP, invocando o serviço e decidindo qual será a próxima view apresentada ao cliente.


public class AuthServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        String identifier = request.getParameter("loginField");
        String secretKey = request.getParameter("passwordField");

        AccountService authService = new AccountService();
        User sessionUser = authService.authenticate(identifier, secretKey);

        if (sessionUser != null) {
            // Sucesso: Armazena o objeto na sessão e redireciona
            request.getSession().setAttribute("LOGGED_USER", sessionUser);
            response.sendRedirect(request.getContextPath() + "/dashboard/home.jsp");
        } else {
            // Falha: Retorna ao login com mensagem de erro via encaminhamento (forward)
            request.setAttribute("errorMessage", "Credenciais Inválidas!");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }
}

4. Encerramento de Sessão (Logout)

Para garantir a segurança, é necessário invalidar a sessão do servidor quando o usuário desejar sair do sistema.


public class TerminateSessionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        HttpSession currentSession = req.getSession(false);
        if (currentSession != null) {
            currentSession.removeAttribute("LOGGED_USER");
            currentSession.invalidate();
        }
        resp.sendRedirect(req.getContextPath() + "/login.jsp");
    }
}

5. Filtro de Segurança (Acesso Restrito)

Um Filter entercepta as requisições para páginas protegidas, verificando se existe um usuário autenticado na sessão ativa.


public class SecurityFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
            throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        HttpServletResponse httpResponse = (HttpServletResponse) res;

        Object userToken = httpRequest.getSession().getAttribute("LOGGED_USER");

        if (userToken == null) {
            // Acesso não autorizado: Redireciona para página de erro ou login
            httpResponse.sendRedirect(httpRequest.getContextPath() + "/unauthorized.jsp");
        } else {
            // Prossegue com a requisição
            chain.doFilter(req, res);
        }
    }
}

6. Configuração no Web Descriptor (web.xml)

Para que os componentes funcionem, as rotas devem ser devidamente mapeadas no arquivo de configuração da aplicação.


<!-- Mapeamento do Servlet de Login -->
<servlet>
    <servlet-name>AuthServlet</servlet-name>
    <servlet-class>com.app.controller.AuthServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>AuthServlet</servlet-name>
    <url-pattern>/doAuth.action</url-pattern>
</servlet-mapping>

<!-- Configuração do Filtro de Proteção -->
<filter>
    <filter-name>SecurityFilter</filter-name>
    <filter-class>com.app.filter.SecurityFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SecurityFilter</filter-name>
    <url-pattern>/dashboard/*</url-pattern>
</filter-mapping>

Tags: java Servlets jdbc MVC Web-Security

Publicado em 10-22 08:45