Como fazer autenticação e bloqueio de senha em JAVA?

1.     public void autenticacao() {
2.             String senhaReal = "123TESTE";
3.             final int chances = 3;  //aqui ele determina o número de tentativas possíveis
4.             int tentativas = 0;  //variável para contar a quantidade de tentativas realizadas
5.             do {

6.                 String senha = new String(jpsSenha.getPassword());
7.                 if (senha.equals(senhaReal)) {
8.                     new Caixa().setVisible(true);
9.                     break; // se acertou, interrompe o laço  
10.                 } else {

11.                     JOptionPane.showMessageDialog(null, "Senha inválida");
12.                     tentativas++; // se errou, incrementa as tentativas  
13.                 }
14.             } while (tentativas < chances);
15.             if (tentativas >= chances) {
16.                 JOptionPane.showMessageDialog(null, "Desculpe, " + chances + " tentativas inválidas, você foi bloqueado!");
17.             }
18.             System.out.println("Fim");

19.         }

Utilizando o console do java trocando o valor de entrada por um Scanner ou um JOPtionPane(input) eu consigo mas quando trabalho com o JTextField ele retorna um loop e incrementa todas as chances de uma só vez. Como fazer para não retornar esse loop?

E porque precisa de um laço?

O ideal é deixar a aplicação chamar o método autenticacao e a classe que faz ter o atributo tentativas fora e não dentro do método algo assim…

public class Login {
    private static final String senhaReal = "123TESTE";
    private static final int chances = 3;
    private static int tentativas; // padrao ja é zero...

    public void autenticacao() {
        if (tentativas >= chances) {
            ...
            return; // pulo do gato aqui... nem prossegue...
        }

        String senha = String.valueOf(jpsSenha.getPassword());
        if (senha.equals(senhaReal)) {
            new Caixa().setVisible(true);
        } else {
            JOptionPane.showMessageDialog(null, "Senha inválida");
            tentativas++;
        }
    }
}

Assim cada vez que o botão login/logar/entrar/ sei la o nome for clicado ou quem chamar o método, a lógica vai ser executada “simulando” um laço (do/while/for/while, etc)…

vlw @rodevops, mas cara porque não funciona quando declaro as variáveis dentro do método. (mas queria saber só porque não estava funcionando, a senha vou pegar do banco).

há só um adendo (return dentro de um método void)?
ficou assim…
1. //declarações
2. private static final String SENHAREAL = “123TESTE”;
3. private static final int CHANCES = 3;
4. private static int tentativas;

5.         public void autenticacao() {
6.             String senha = new String(jpsSenha.getPassword());
7.             if (senha.equals(SENHAREAL)) {
8.                 new Caixa().setVisible(true);
9.             } else {
10.                 JOptionPane.showMessageDialog(null, "Senha inválida");
11.                 tentativas++; // se errou, incrementa as tentativas  
12.             }
13.             if (tentativas >= CHANCES) {
14.                 JOptionPane.showMessageDialog(null, "Desculpe, " + CHANCES + " tentativas inválidas, você foi bloqueado!");
15.                 System.exit(0);
16.             }

17.         }

Porque dentro do método você vai resetar o valor dela (isso se não usasse loop)…

O pulo do gato como tinha mencionado, em java todo método retorna alguma coisa mesmo sendo void e quando se declara um return vazio (void)… o java entende que deve retornar a quem chamou o método (envolve stack de chamadas, coisas que você não precisa aprender agora…), o que interessa pra você por enquanto é que funciona :joy:, mas use-o com moderação…

O que estou tentando te mostrar é que não faz sentido usar loop para isso, você deve deixar a aplicação seguir seu fluxo naturalmente e usar os controles adequadamente pegou?

Outra coisa, como vc mencionou que vai pegar a senha do banco, a ordem dos if’s faz diferença… por exemplo: vale a pena você ir no banco sabendo que as tentativas se esgotaram pra depois você informar e encerrar a aplicação?

Obs: coloquei o if naquela ordem por essa razão… vai pensando a longo prazo, quanto menos vc precisar usar recursos externos (conexão com banco, abertura de arquivos, etc) melhor…

Você disse que vai pegar a senha do Banco de Dados, eu não sei bem como o pessoal implementa isso, mas acredito que o mais seguro atualmente é criptografar a senha - criar um “Hash Criptográfico” dela (ou “Resumo Criptografico”) - e salvar esse Hash no Banco de Dados.

Assim, se um alguém hackear o BD não terá acesso a todas as senhas dele, terá acesso apenas aos Hashes.

Para fazer um Hash, você pode usar o SHA2, ou outra tecnologia; mas é importante gerar um “salt” e concatená-lo a senha antes de criptografá-la, para que a senha não possa ser descoberta a partir do Hash através de um site como esse.

Na hora de verificar se o usuário digitou a senha correta, você adiciona o salt e usa o algoritmo de criptografia para gerar o Hash da senha digitada, então, pega o Hash do BD e compara para ver se ambos os Hashes são iguais (se são iguais a senha está certa).

O link abaixo pode lhe ajudar a entender melhor (mas note que o MD5 citado no artigo parece já estar obsoleto, use criptografia de 256 ou 512 bits):

A wikpedia também pode ajudar a entender os “salts”: