Servlet de Login

10 respostas
D

Boa tarde,

Estou com algumas dúvidas e gostaria das dicas de vocês para fazer um bom servlet para autenticar meus usuários no sistema.

Primeiro alguns pré-requisitos

  • Precisa ser em MVC
  • O sistema tem telas especificas para Administradores e Usuários, ou seja, conforme sua permissão ele abre as paginas X ou Y
  • Os usuários, senhas e nível de acesso (Administrador/Usuário) já estão cadastrados no banco de dados.

O que eu já fiz:

  • Criei a JSP, onde o forma chama o Servlet (doPost)
  • Criei uma classe chamada Login que gera um objeto com usuario e senha
  • Criei uma classe pra conexão com o banco de dados (MySQL - funcionando)
  • Criei a classe DAO que faz um select no banco e pega as informacoes do usuário digitado
  • Criei o servlet que instancia o objeto Login e passa esse objeto para a classe DAO que pesquisa no banco.

Minha dúvida é…

Preciso que a classe DAO retorne pro servlet se o usuário é ou não válido e também preciso dizer se esse usuário é ou não administrador do sistema.

Depois disso preciso criar uma session pra guardar a informação do usuário e o nivel de permissão, que vão ser usados pra consultar mais tarde nas outras telas.
Como devo proceder?

JSP

<%@ page contentType="text/html; charset=utf-8" language="java" import="java.sql.*" errorPage="" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>SGC - Sistema de Gerenciamento Condominial</title>
<style rel="stylesheet" type="text/css" />

html, body { padding: 0; margin: 0;}
p {padding: 0; margin: 0;}
#geral {width: 100%; height: 100%;}
#fundo {width: 100%; height: 200px; background-image: url(fundologin.png); position: absolute; top: 50%; margin-top: -100px;}
#logoform {width: 455px; height: 200px; margin: 0 auto;}
#logo {float:left; margin-top: 35px;}
#form {float:right; margin-top: 40px; font-family: Tahoma; font-size: 10px;}
#campo {border: 1px solid #CCC; height: 20px; width: 150px; margin-bottom: 5px; }
#botao {height: 25px; width: 150px; background: #FFF; margin-top: 8px; font-family:Tahoma;}

</style>
</head>

<body>
<div id="geral">
	<div id="fundo">
    	<div id="logoform">
            <img id="logo" src="logo248x130.png"/>
            <form id="form" method="post" action="Login">
            	<p>Usuário</p>
       		<p><input id="campo" name="usuario" type="text" /></p>
                <p>Senha</p>
            	<p><input id="campo" name="senha" type="password" /></p>
            	<p><input id="botao" name="entrar" type="submit" value="ENTRAR"/></p>
            </form>
        </div>
    </div>
</div>
</body>
</html>

Classe pra instanciar os Objetos de Login

package Object;


public class LoginObject {
   private String usuario;  
   private String senha;  
  
     
   public String getUsuario() {  
      return usuario;  
   }  
     
   public void setUsuario(String usuario) {  
      this.usuario = usuario;  
   }  
     
   public String getSenha() {  
      return senha;  
   }  
     
   public void setSenha(String senha) {  
      this.senha = senha;  
   }  
}

DAO que deveria retornar alguma coisa, por enquanto só ta fazendo uns println

package DAO;

import Conexao.Conexao;
import java.sql.Connection;
import java.sql.PreparedStatement;  
import java.sql.ResultSet;
import java.sql.SQLException; 
import Object.LoginObject;

/**
 *
 * @author murilo
 */
public class LoginDAO extends Conexao{

    public static void Login(LoginObject login) throws SQLException, ClassNotFoundException {  
        
        String sql = "SELECT * FROM condomino WHERE usuario=? AND senha=?";
        
        Connection con = GetConexao();  
        
        PreparedStatement psmt = con.prepareStatement(sql);
        
        psmt.setString(1, login.getUsuario());  
        psmt.setString(2, login.getSenha());
        
        ResultSet rs = psmt.executeQuery();
      
        if(rs.next()){
            System.out.println(rs.getString("usuario"));
            System.out.println(rs.getString("senha"));
            System.out.println(rs.getString("administrador"));
        } else {
            System.out.println("Nenhum usuario!");
        }
        psmt.close();
        rs.close();
        con.close();  
  
    }

}

Servlet que deveria receber o retorno da DAO e criar a session.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Servlet;

import java.io.IOException;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import Object.LoginObject;
import DAO.LoginDAO;

/**
 *
 * @author murilo
 */
public class LoginServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, SQLException, ClassNotFoundException {
        response.setContentType("text/html;charset=UTF-8");
        
        // joga usuario e senha nas strings
        String usuario = request.getParameter("usuario");
        String senha = request.getParameter("senha");
        
        // instancia o objeto login que vai ser usado na DAO
        LoginObject login = new LoginObject();
        login.setUsuario(usuario);
        login.setSenha(senha);
        
        // define a pagina de retorno como null
        String pagina = null;
        
        // chama a dao que verifica o login no banco e retorna se é administrador ou não
        LoginDAO.Login(login);
        
        response.setContentType("text/html;charset=UTF-8");
        
        if(usuario.equals("Admin") && senha.equals("teste")) {
            HttpSession sessao = request.getSession();
            sessao.setAttribute("login", usuario);
            sessao.setAttribute("permissao", "Admintrador");
            pagina = "Administrador/home.jsp";
            response.sendRedirect(pagina);
	}
        else if(usuario.equals("Usuario") && senha.equals("teste")) {
            HttpSession sessao = request.getSession();
            sessao.setAttribute("login", usuario);
            sessao.setAttribute("permissao", "Usuario");
            pagina = "Usuario/home.jsp";
            response.sendRedirect(pagina);
        }
        else {
            pagina = "index.jsp";
            response.sendRedirect(pagina);
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            processRequest(request, response);
        } catch (SQLException ex) {
            Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            processRequest(request, response);
        } catch (SQLException ex) {
            Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

Obrigado quem puder me dar umas dicas ae! =)

10 Respostas

nel

Oi!

Infelizmente faz muito tempo que não lido com Servlets dessa forma, usando-se JSP.
Não sei lhe afirmar como faria para controle de acesso do usuário a determinadas páginas, mas acredito que idéia seja de jogar na Sessão como está fazendo mesmo.
Para cada página é capturar o usuário da sessão e verificar se o logado tem ou não acesso aquela função.

Para algo mais legível, o ideal é que nem fosse habilitado determinadas funções do sistema para usuário comum, como por exemplo, cadastrar um apartamento (supondo que seja uma função exclusiva do administrador).

Sobre o seu DAO, bastaria modificar isso:

public class LoginDAO extends Conexao{   
  
    public static boolean Login(LoginObject login) throws SQLException, ClassNotFoundException {     
           
        String sql = "SELECT * FROM condomino WHERE usuario=? AND senha=?";   
           
        Connection con = GetConexao();      
        try {          
        PreparedStatement psmt = con.prepareStatement(sql);   
           
        psmt.setString(1, login.getUsuario());     
        psmt.setString(2, login.getSenha());   
           
        ResultSet rs = psmt.executeQuery();   
         
        if(rs.next()){   
            return true;
        } else {   
            return false;        
        }   
        } finally {
        psmt.close();   
        rs.close();   
        con.close();     
       }
    }   
  
}

Perceba que adicionei um bloco try-finally ao seu código. Isso obriga que o seu método vai sempre executar os close, no PreparedStatement, ResultSet e no Connection.
Só mais dois detalhes sobre isso:

1 - Verifique no finally se as variavéis não são nulas, podem ser caso ocorra exceção.
2 - Faça o tratamento com try-cath das exceções, ou deseja que elas sejam jogadas "para cima" e caim lá na sua página JSP sem tratamento algum? Fica feio aparecer ao usuário algo como "SQLException: bla bla bla" não acha? :)

Abraços.

nel

Oi!

Infelizmente sobre a questão de como tratar o acesso as paginas no JSP com Servlets não poderia ajudar muito, trabalhei com Struts e JSP mas faz bastante tempo (praticamente 2 anos), então não me recordo como na época eu tratava essa situação. Mas nada que uma pesquisa pela net não resolva.
Creio que usar a sessão para saber o usário faz todo sentido e seja o caminho correto, só para ficar algo mais "bonito" e "legível" você pode nem sequer mostrar ao usuário comum páginas restritas, somente quando o usuário for de nível administrador tais páginas devam ser exibidas.

No JSF isso pode ser feito com um da vida, em JSP teria de dar uma olhada.
Sobre o seu select referente ao usário, eu modificaria o seguinte:

public static boolean Login(LoginObject login) throws SQLException, ClassNotFoundException {     
           
        String sql = "SELECT * FROM condomino WHERE usuario=? AND senha=?";   
           
        Connection con = GetConexao();     
        try {
        PreparedStatement psmt = con.prepareStatement(sql);   
           
        psmt.setString(1, login.getUsuario());     
        psmt.setString(2, login.getSenha());   
           
        ResultSet rs = psmt.executeQuery();   
         
        if(rs.next()){   
           return true;
        } else {   
           return false;
        }
        } finally {   
        psmt.close();   
        rs.close();   
        con.close();     
        }
     
    }   
  
}

Perceba três detalhes:

1 - Alterei o retorno para booleano. Caso ele cai no rs.next() signifca que encontrou o registro, portanto, usuário existe, caso contrário, é false.

2 - Adicionei um bloco finally, isso é muito importante para sempre fechar os PreparedStatement, ResultSet e Connection, de modo a não ter problemas com o Pool. Dependendo do container web que utilizar, podes até configurar o mesmo para gerenciar isso para você. Só um detalhe muito importante, verifique se as variavéis não são nulas dentro do finally antes de executar o close, ok?

3 - Use um bloco try-cath no seu método, caso contrário, vai "lançar para cima" as possíveis exceções e cair em sua página JSP. Fica feio aparecer ao usuário "SQLException: bla bla bla" certo?

Forte abraço.

D

O problema é que essa pesquisa q vc fez só serve pra validar se o usuário existe ou não…

ainda sim preciso validar se é ou não administrador.

Posso por no return uma variavel?

por exemplo

String permissao = null;

se ele for administrador

permissao = “admin”;

se ele for usuario

permissao = “usuario”;

se ele nao for nenhum dos dois

permissao = “erro”;

Dai eu trato esses retornos no servlet…

edit:

as paginas q ele nao tem permissão nem mostra q existem pra ele…
mais se por ventura ele digitar o caminho no browser…
não existe nada que valide pra dizer q ele não tem acesso…

nel

Oi!

Interessante.
Se você tem a variavél no seu Banco de dados que indica o nível do usuário, é bem simples.
Vamos usar OO e Java, que tal? Crie um Enumeration e deixa que ele faça o controle para você.

Podes fazer algo assim:

enum Login {
		ADMINISTRADOR (1, "Administrador"),
		
		NORMAL_USER (2, "Usuario"),

                                UNIDENTIFIED (3, "Não Identificado");
		
		private Login(int code, String description) {
			this.code = code;
			this.description = description;
		}
		
		private int code;
		private String description;
		
		public static Login getLoginByCode(int code) {
			for(Login login : Login.values()) {
				if(login.getCode() == code) {
					return login;
				}
			}
			throw new IllegalArgumentException(code + " is not valid!");
		}
		
		public static Login getLoginByDescription(String description) {
			for(Login login : Login.values()) {
				if(login.getDescription().equalsIgnoreCase(description)) {
					return login;
				}
			}
			throw new IllegalArgumentException(description + " is not valid!");
		}
		
		public int getCode() {
			return code;
		}
		public void setCode(int code) {
			this.code = code;
		}
		public String getDescription() {
			return description;
		}
		public void setDescription(String description) {
			this.description = description;
		}		
	}

Se você guarda como um código, que eu acho mais fácil do que uma String, para que tu não tenha problemas com acentuação, por exemplo, podes fazer isso:

if(rs.next()) {
    int code = rs.getInt("administrador");
    return Login.getLoginByCode(code);
} else {
   return Login.UNIDENTIFIED;
}

Agora basta lançar um Switch no seu Servlet que fica fácil de saber quem está logado.
Abraços.

P.s: ainda dá de usar Polimorfismo, se achar interessante, podes estudar uma maneira de fazer isso. Senão, o switch resolve facilmente.

nel

dombeck:

edit:

as paginas q ele nao tem permissão nem mostra q existem pra ele…
mais se por ventura ele digitar o caminho no browser…
não existe nada que valide pra dizer q ele não tem acesso…

Pois é. Um JBoss da vida configurado corretamente bloquearia isso para você. Em outros containers ou AS teria de pesquisar e verificar como é possível.
Senão me engano, sempre que você digita uma URL e acessa diretamente pelo brownser, utiliza-se o método GET da Servlet.

Para tal, você pode testar se realmente seu método GET é invocado, caso seja, faça a validação.
Verifique se há usuário na sessão e caso não exista, direciona o usuário para uma página de erro.
É uma idéia.

Abraços.

D

Fiquei meio confuso…

não posso fazer um novo método dentro da DAO que verifica se é administrador ou não e tb retorna true ou false…

dai faço duas chamadas no meu servlet…

=)

é mais simples e acho q pode funcionar tb!

nel

dombeck:
Fiquei meio confuso…

não posso fazer um novo método dentro da DAO que verifica se é administrador ou não e tb retorna true ou false…

dai faço duas chamadas no meu servlet…

=)

é mais simples e acho q pode funcionar tb!

Claro que pode, se tu acha menos confuso e mais simples, faça.
Isso foi apenas uma sugestão. Só um detalhe, evite usar o ‘*’ em Select, busque apenas as colunas que precisa, pois vai estar trazendo informações desnecessária, dependendo o caso.

Abraços.

D

nel…

naquela sua sugestão da minha DAO ali deu um problema…

no finally

finally {

psmt.close();

rs.close();

con.close();

}

ele não reconehce o psmt.close() e o rs.close();
porém o con.close() sim

porque será?

nel

dombeck:
nel…

naquela sua sugestão da minha DAO ali deu um problema…

no finally

finally {

psmt.close();

rs.close();

con.close();

}

ele não reconehce o psmt.close() e o rs.close();
porém o con.close() sim

porque será?

Foi um exemplo, tinha de ter modificado.
Veja:

try { String teste = "João"; } finally { teste = ""; }

A String ‘teste’ pertence exclusivamente ao bloco try - finally, e não a todo o método que esteja incluso esse trecho de código entende?
Para reconhecer, teria de fazer isso:

String teste = null; try { teste = "João"; } finally { if(null != teste) System.out.println("Nome: " + teste); }

Entendeu? :slight_smile:
Faça igual para todas as variavéis que citei para o seu Finally.

Abraços.

D

Essa parte ta resolvida!

Alguém mais tem sugestões sobre formas de permitir e bloquear usuários em JSPs?

Criado 8 de agosto de 2011
Ultima resposta 8 de ago. de 2011
Respostas 10
Participantes 2