[RESOLVIDO] Criptografia MD5 + spring

Olá tudo bem?
Bom estou tentando colocar criptgrafia, criei um metodo para criptografar as senhas que iram no banco de dados:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.rpctv.siseng.etc;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 *
 * @author ricardo
 */
public class Criptografia {

    public static String md5(String senha) {
        String sen = "";
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        BigInteger hash = new BigInteger(1, md.digest(senha.getBytes()));
        sen = hash.toString(16);
        return sen;
        
    
    }
}

Depois eu chamei esse medo na hora de salvar a senha, porque assim vai para o banco de dados criptografada(e esta indo, sem problemas nenhum até aqui):

public void setPassword(String password) {
        this.password = Criptografia.md5(password);
    }

o Problema é agora, eu uso o spring security, e nao tenho muita ideia de como comparar a senha “normal” que o usuario digitou com a senha criptografada no banco de dados, sei que tenho que criptogafar a senha que o usuario digitou no login e comparar as duas senhas ja criptografadas, só nao sei como fazer isso.
Analisei um pouco e percebi que o spring security faz a comparação fazendo um select descrito no application context:

<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:b="http://www.springframework.org/schema/beans"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans.xsd
                             http://www.springframework.org/schema/security
                             http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <http auto-config="true" access-denied-page="/negado.xhtml" use-expressions="true">
     <intercept-url pattern="/view/**" access="hasAnyRole('ROLE_ADMIN','ROLE_TECNICO','ROLE_USER','ROLE_OPEC','ROLE_OPERADOR','ROLE_USUARIO','ROLE_JORNALISMO', 'ROLE_PROGRAMACAO', 'ROLE_OPECCORD', 'ROLE_ADMINISTRACAO', 'ROLE_ROTEIRO' )"/>   
        <form-login login-page="/login.xhtml" authentication-failure-url="/login.xhtml?erro=true"/>
        
        <session-management>
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
        </session-management>
       
    </http>
    <authentication-manager>
        <authentication-provider>  
         
           <!--  <security:password-encoder hash="md5"/> -->
            
            
         
            <jdbc-user-service data-source-ref="dataSource"
               users-by-username-query="SELECT username, password, enable FROM usuario WHERE username=?" <!-- MAIS ESPECIFICO AQUI -->
               authorities-by-username-query="SELECT username as username, nome as authority FROM usuarioautorizacao WHERE username=?"
            />
        </authentication-provider>
    </authentication-manager>
    
    
    <b:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
        <b:property name="url" value="jdbc:oracle:thin:@xxxxxxxxxxxxx:XE"/>
        <b:property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
        <b:property name="username" value="xxxxxxxxxx" />
        <b:property name="password" value="xxxxxxxxxxxxx" />
    </b:bean>

</b:beans>

só nao consigo criptografar essa busca para o spring criptografar, buscar e comprar as duas senhas ja criptografadas.
Alguem pode me ajudar?

se vc deixar somente o

esse trecho ira fazer essa função do codigo md5 que vc criou, pois ele pega a senha sem criptografia e o transforma e consulta… e vice-versa…

agora esse seu metodo só teria utilidade na hora de cadastrar uma senha no banco.

Então eu tenho tanto usuario com senha criptografada com o metodo que criei, como usuario sem criptografia, quando ativo essa linha ele nao deixar nem o usuario com a senha criptografada logar e nem o com a senha normal.

a senha tem que ter sido salva no banco com criptografia md5, vc nao precisa passar a senha criptografada pro spring ,caso vc tenha colocado aquela tag, basta passar a senha normal, que ele converte automaticamente para md5.

para vc testar, criptografa uma senha, e a salva no banco… depois digita a senha no sistema sem passar por esse metodo que vc criou, vera que ele faz tudo sozinho, vc nem precisa se preoculpar em criptografar ou decriptografar.

Bom vamos la;
estou usando esse metodo que criei(Criptografia) para criptografar as senhas de novos usuario que seram salvos assim as senha ja estaram criptografadas no banco de dados.
Ao colocar essa linha no application context aparentemente ele funciona, porem nao consegue comparar a senha criptografada no banco de dados com a senha que o usuario digitou.

Eu teria que deixar no banco de dados sem criptgrafia e o application context iria criptografar para mim? e depois comparar os 2 criptografados.

[quote=alextr]Bom vamos la;
estou usando esse metodo que criei(Criptografia) para criptografar as senhas de novos usuario que seram salvos assim as senha ja estaram criptografadas no banco de dados.
Ao colocar essa linha no application context aparentemente ele funciona, porem nao consegue comparar a senha criptografada no banco de dados com a senha que o usuario digitou.

Eu teria que deixar no banco de dados sem criptgrafia e o application context iria criptografar para mim? e depois comparar os 2 criptografados.[/quote]

pelo que vi, vc criptografa a senha primeiro e depois ele consulta no banco certo?
desse jeito nao funciona… pq ele vai pegar essa senha criptografada e criptografar novamente em MD5 e entao comparar, e isso vai dar false… a senha que tem que ser enviada pro spring é a senha limpa sem criptografia, ele faz a criptografia e compara e te retorna true ou false, lembrando que tem que estar criptografada no banco tbm…

posta sua classe de usuario? para eu ver o que vc faz nela… o problema quase certeza que esta nela…

OPa a classe usuario:

package br.com.rpctv.siseng.entidade;

import br.com.rpctv.siseng.etc.Criptografia;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.Cascade;
import org.springframework.util.DigestUtils;

/**
 *
 * @author ricardo
 */
@Entity
@Table(name = "usuario", schema = "teste2")
public class Usuario implements Serializable {

    @Id
    @Column(name = "username")
    private String username = "";
    @Column(name = "password")
    private String password;
    @Column(name = "enable")
    private boolean enable = true;
    @Column(length = 13)
    private String rg;
    @Column(name = "fechaOcorrencia")
    private boolean fechaOcorrencia = false;
    @Column(name = "alocaOcorrencia")
    private boolean alocaOcorrencia = false;
    @Column(name = "cadastraEquipamento")
    private boolean cadastroEquipamento = false;
    @Column(name = "visuOcorrencia")
    private boolean visuOcorrencia;
    @Column(length = 6)
    private Long ramal;
    @Temporal(TemporalType.DATE)
    private Date admissao;
    @Column
    private String matricula;
    @Column(length = 15)
    private String cpf;
    @Column(length = 250)
    private String nome;
    @Column(length = 15)
    private String telefone_1;
    @Column(length = 15)
    private String celular;
    @Column(length = 100)
    private String email_corp;
    @Column(length = 100)
    private String email_part;
//    
//    @Column
//    private boolean escala;   
    @Column(length = 100)
    private String endereco;
    @Column(length = 80)
    private String bairro;
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date data_cadastro;
    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "usuarioAutorizacaoPK.usuario")
    private List<UsuarioAutorizacao> usuarioAutorizacoes = new ArrayList<UsuarioAutorizacao>();
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "id_unidade")
    private Unidade unidade;
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "id_funcao")
    private Funcao funcao;
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "id_cidade")
    private Cidade cidade;
    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "ocorrenciaUsuarioPK.usuario")
    private List<OcorrenciaUsuario> ocorrenciasUsuarios = new ArrayList<OcorrenciaUsuario>();
    
    public List<OcorrenciaUsuario> getOcorrenciasUsuarios() {
        return ocorrenciasUsuarios;
    }

    public void setOcorrenciasUsuarios(List<OcorrenciaUsuario> ocorrenciasUsuarios) {
        this.ocorrenciasUsuarios = ocorrenciasUsuarios;
    }

    public boolean getVisuOcorrencia() {
        return visuOcorrencia;
    }

    public void setVisuOcorrencia(boolean visuOcorrencia) {
        this.visuOcorrencia = visuOcorrencia;
    }

    public boolean getCadastroEquipamento() {
        return cadastroEquipamento;
    }

    public void setCadastroEquipamento(boolean cadastroEquipamento) {
        this.cadastroEquipamento = cadastroEquipamento;
    }

    public Usuario() {
    }

    public Usuario(String username) {
        this.username = username;
    }

    public boolean getFechaOcorrencia() {
        return fechaOcorrencia;
    }

    public void setFechaOcorrencia(boolean fechaOcorrencia) {
        this.fechaOcorrencia = fechaOcorrencia;
    }

    public boolean getAlocaOcorrencia() {
        return alocaOcorrencia;
    }

    public void setAlocaOcorrencia(boolean alocaOcorrencia) {
        this.alocaOcorrencia = alocaOcorrencia;
    }

    public Unidade getUnidade() {
        return unidade;
    }

    public void setUnidade(Unidade unidade) {
        this.unidade = unidade;
    }

    public Cidade getCidade() {
        return cidade;
    }

    public void setCidade(Cidade cidade) {
        this.cidade = cidade;
    }

    public Funcao getFuncao() {
        return funcao;
    }

    public void setFuncao(Funcao funcao) {
        this.funcao = funcao;
    }

    public List<UsuarioAutorizacao> getUsuarioAutorizacoes() {
        return usuarioAutorizacoes;
    }

    public void setUsuarioAutorizacoes(List<UsuarioAutorizacao> usuarioAutorizacoes) {
        this.usuarioAutorizacoes = usuarioAutorizacoes;
    }

    public Date getAdmissao() {
        return admissao;
    }

    public void setAdmissao(Date admissao) {
        this.admissao = admissao;
    }

    public String getCelular() {
        return celular;
    }

    public void setCelular(String celular) {
        this.celular = celular;
    }

    public String getCpf() {
        return cpf;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }

    public Date getData_cadastro() {
        return data_cadastro;
    }

    public void setData_cadastro(Date data_cadastro) {
        this.data_cadastro = data_cadastro;
    }

    public String getEmail_corp() {
        return email_corp;
    }

    public void setEmail_corp(String email_corp) {
        this.email_corp = email_corp;
    }

    public String getEmail_part() {
        return email_part;
    }

    public void setEmail_part(String email_part) {
        this.email_part = email_part;
    }

    public boolean isEnable() {
        return enable;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }

//    public boolean getEscala() {
//        return escala;
//    }
//
//    public void setEscala(boolean escala) {
//        this.escala = escala;
//    }
//    
    public String getMatricula() {
        return matricula;
    }

    public void setMatricula(String matricula) {
        this.matricula = matricula;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = Criptografia.md5(password);//CRIPTOGRAFIA SENDO SALVA NO BANCO DE DADOS EM MD5
    }

    public Long getRamal() {
        return ramal;
    }

    public void setRamal(Long ramal) {
        this.ramal = ramal;
    }

    public String getRg() {
        return rg;
    }

    public void setRg(String rg) {
        this.rg = rg;
    }

    public String getTelefone_1() {
        return telefone_1;
    }

    public void setTelefone_1(String telefone_1) {
        this.telefone_1 = telefone_1;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getBairro() {
        return bairro;
    }

    public void setBairro(String bairro) {
        this.bairro = bairro;
    }

    public String getEndereco() {
        return endereco;
    }

    public void setEndereco(String endereco) {
        this.endereco = endereco;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Usuario other = (Usuario) obj;
        if ((this.username == null) ? (other.username != null) : !this.username.equals(other.username)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 59 * hash + (this.username != null ? this.username.hashCode() : 0);
        return hash;
    }

    @Override
    public String toString() {
        return username;
    }
}

Vamos ver se eu entendi:
se eu colocar o:

<password-encoder hash="md5"/> no application context, ele vai salvar no banco em md5 e depois comparar?
Lembrando que essas senhas tem que esta criptografadas no banco de dados.

Cara me tira uma duvida:

eu tenho que criptografar a senha no banco de dados ai eu coloco aquele coigo no application context, e depois tenho que colcoar isso?

<password-encoder hash="md5"/>
        <user-service>
            <user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
            <user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" />
            <user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a" authorities="ROLE_USER" />
            <user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_USER" />
        </user-service>

eu tenho que colocar usuario por usuario? e passar a senha criptografada?
Cara eu se eu tiver mais de 200 usuarios teria que colcoar usuario por usuario no application context?

Cara esse metodo ai de cima, é comparação para poucos usuarios, se for para muitos como no meu caso é usado isso:

 <authentication-manager>
        <authentication-provider>  
         
   <password-encoder hash="md5"/>
            
           
        
        
            <jdbc-user-service data-source-ref="dataSource"
               users-by-username-query="SELECT USERNAME,MD5(PASSWORD) FROM USUARIO WHERE username=?"
               authorities-by-username-query="SELECT username as username, nome as authority FROM usuarioautorizacao WHERE username=?"
                          
 />
      
        </authentication-provider>
    </authentication-manager>

Eu uso o banco de dados ORACLE 10g, eu faço esse slect direto no banco de dados: SELECT USERNAME,MD5(PASSWORD) FROM USUARIO; converte perfeitamente a senha normal para MD5 e que é a mesma manei que meu metodo criptografia que salva no banco de dados.
Porem ao logar ele da sistema indisponivel para manutenção(eu sei que é tratamento de erros, e nao fui eu que fiz), mais se eu não coloco nada no login e senha ele fala que esta errado.
Traduzindo tudo isso: Se eu digitar a senha CERTA ele da servidor indisponivel para a manutenção, e se a senha ou usuario errado da erro normal.
Cara nao deveria dar servidor indiponivel deveria entrar ele esta validado certo.

[quote=alextr]Cara esse metodo ai de cima, é comparação para poucos usuarios, se for para muitos como no meu caso é usado isso:

 <authentication-manager>
        <authentication-provider>  
         
   <password-encoder hash="md5"/>
            
           
        
        
            <jdbc-user-service data-source-ref="dataSource"
               users-by-username-query="SELECT USERNAME,MD5(PASSWORD) FROM USUARIO WHERE username=?"
               authorities-by-username-query="SELECT username as username, nome as authority FROM usuarioautorizacao WHERE username=?"
                          
 />
      
        </authentication-provider>
    </authentication-manager>

Eu uso o banco de dados ORACLE 10g, eu faço esse slect direto no banco de dados: SELECT USERNAME,MD5(PASSWORD) FROM USUARIO; converte perfeitamente a senha normal para MD5 e que é a mesma manei que meu metodo criptografia que salva no banco de dados.
Porem ao logar ele da sistema indisponivel para manutenção(eu sei que é tratamento de erros, e nao fui eu que fiz), mais se eu não coloco nada no login e senha ele fala que esta errado.
Traduzindo tudo isso: Se eu digitar a senha CERTA ele da servidor indisponivel para a manutenção, e se a senha ou usuario errado da erro normal.
Cara nao deveria dar servidor indiponivel deveria entrar ele esta validado certo.[/quote]

entao desculpa demora… seguinte… no seu metodo de setPassword, vc ta forçando ele a criptografar sempre… não precisa… so usa o seu metodo de criptografar quando for realmente necessario que seria na hora de persistir…

segundo ponto

se vc colocar ele automaticamente, vai criptografar para vc… e descriptografar… vc nem precisa se preoculpar com isso, a sua unica preocupação é garantir que sera salvo no banco com a criptografia MD5…

remove do setPassword o criptografia… e coloca isso so no momento de atualizar e persistir um novo dado… o que o spring security faz é apenas consultar no banco se as informações (ROLES) estao de acordo com o estabelecido…

para ficar mais simples… exemplo…

Estou na tela de login… digito minha senha e mando a requisição… no modo que vc ta fazendo ele ao colocar a senha ele vai criptografar… para exemplo 3567890876345678 e depois vai bater no spring security e ele vai criptografar mais uma vez a senha ja criptografado… gerando outra senha 45678945678 e quando ele vai no banco ele compara se
3567890876345678 == 45678945678 … logo isso da false…

Cara não deu.
Tirei a criptografia do usuario, removi tudo, porem ja tinha um usuario com a senha criptografada em MD5, e so coloquei o:

e nao foi nem com a senha criptografada e nem normal, ele nao deixar nenhum entrar da erro.

[quote=alextr]Cara não deu.
Tirei a criptografia do usuario, removi tudo, porem ja tinha um usuario com a senha criptografada em MD5, e so coloquei o:

e nao foi nem com a senha criptografada e nem normal, ele nao deixar nenhum entrar da erro.[/quote]

estranho… eu consegui fazer um exemplo aqui e funcionou, a unica diferença é que eu fiz usando a minha implementação…

da uma olhada no projeto que fiz no github…

https://github.com/ThiagoSouzaCardoso/Aeroport_Module

ve se ajuda em algo… XD

Bom ajudou um pouco, persebi que o spring security nao pode fazer a verificação do login para mim, tenho que criar um metodo para poder fazer isso.
Esse metodo eu chamo no application context e la eu faço a verificação.
O problema é que meus conhecimentos em java não os melhores e precisa saber com faço essa validação de login, com usuario, senha criptografada em md5, e autorizações.

AEAEEAEAEAEEAEAEAEEAEAEAEEAEAEEAA CONSEGUI.

Eu estava colocando a criptografia na entidade, entao toda vez que eu salva-se um usuario novo ele criptografava e ia para o banco de dados certo. Até ai ok.
Porem eu NÃO POSSO colcoar a criptografia na entidade porque quando for comprar novamente eu irei chamar essa entidade e ira fazer a criptografia 2 vezes.

Muito obrigado por me ajudar darklordkamui.
Era o problema de eu estar colocando a criptografia na entidade e ai criptografava 2 vezes .

Ai o que fiz:

Na nova senha que o usuario escolher eu coloquei a criptografia na novasenha e na novasenha2 pois uma verefica a outra antes de alterar, e entao as duas tem que estar criptografadas para que possa ser feito a comparação se não não da.

Então em UsuarioBean ficou assim, quando o usuario digitar uma nova senha criptografa ela e salva no banco de dados.

 public String getNovaSenha2() {
        return novaSenha2;
    }

    public void setNovaSenha2(String novaSenha2) {
        this.novaSenha2 = Seguranca.md5(novaSenha2);
    }

    public String getNovaSenha() {
        return novaSenha;
    }

    public void setNovaSenha(String novaSenha) {
        this.novaSenha = Seguranca.md5(novaSenha);
    }
public String getSenhaAtual() {
        return senhaAtual;
    }

    public void setSenhaAtual(String senhaAtual) {
        this.senhaAtual = Seguranca.md5(senhaAtual);
    }

ainda não fiz em salvar um novo usuario mais depois disso isso vai ser facil.
Muito obrigado a todos que me ajudaram.

CONSEGUI tambem ao salvar um novo usuario:

la na ENTIDADE USUARIO, eu ahco que o problema não era na entidade mais sim que meu select esta em md5 e eu estava forçando o spring security ler em md5 tambem ai ele criptografava 2 vezes.
Entao é o seguinte coloquei a criptografia seguranca em UsuarioBean como motrado na mensagem logo acima e coloquei a criptografia no set da senha em Entidade Usuario:

public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = Seguranca.md5(password);
    }

e funcionou tanto na alteracao como em um novo usuario.

Muito Obrigado Por tudo vlw.

a criptografia pode ficar na entidade porem ao comprar a novaSenha2 que é a que via para o banco tambem ele passa pela entidade e criptografa 2 vezes, porque quando eu mudo a senha(nao criou uma nova eu somente mudo) ele criptografa 2 vezes entao o que fiz:

Tirei a criptografia na entidade usuarioBean e tirei a criptografia da novaSenha2, e habilitei somente onde ira comparar a novaSenha2 com a novaSenha e ficou assim:
Onde ira salvar o usuario tem uma compararção é socriptografar a novaSenha2:

public void salvarUsuario(ActionEvent event) {
        try {
 if (!"".equals(senhaAtual) || !senhaAtual.isEmpty()) {
                if (Seguranca.md5(novaSenha2).equals(novaSenha)) {//bem aqui
                    nome.setPassword(novaSenha2);
                }

e tambem tive que colocar na verificação da senha para ver se a novaSenha2 é igual a novaSenha então como criptografei a novaSenha e a novaSenha2 não esta criptografada tive que colar a criptografia nas verificações:

 public Boolean verificaSenha(AjaxBehaviorEvent event) {
        if (senhaAtual.equals(nome.getPassword())) {
            liberaNovaSenha = Boolean.TRUE;
            return true;
        }

é isso ai, funciou perfeitamente o post acima desse está errado não sei o porque funcinou mais esse está funcionando perfeitamente.

parabens por achar a solução.

agora belas senhas essa que voce setou para os usuários.

peter = opal
scott = wombat
dianne = emu
rod = koala

dica: NUNCA use md5 puro para hashear uma senha, md5 é extremamente facil de quebrar, procure alguns outro algoritmo para melhor segurança

Use pelo menos salt ou então pbkdf2 - não importa se é MD5 ou SHA-512, se você tiver uma lista de senhas comuns, é extremamente simples quebrar .

Veja em: