terça-feira, 2 de dezembro de 2014

Força Senha

Componente para medir a força da senha

Este post irá exibir como implementar um medidor de força de senha utilizando o padrão de projeto Template Method, tendo como regra para o cálculo o valor do desvio padrão entre os caracteres de acordo com a tabela ASCII.

Bom, para começar vamos desenvolver uma classe abstrata Senha, que será nossa super classe

/**
 * Classe abstrata para medir a forca da senha
 */
public abstract class Senha {
 
 private Forca forcaSenha;
 private Pattern patter = this.getPatter();
 private Matcher matcher;
 private int frequencia;
 private int tamanhoInicial;
 private int tamanhoFinal;
 private Double desvioPadrao;

 public int getTamanhoInicial() {
  return tamanhoInicial;
 }

 public void setTamanhoInicial(int tamanhoInicial) {
  this.tamanhoInicial = tamanhoInicial;
 }

 public int getTamanhoFinal() {
  return tamanhoFinal;
 }

 public void setTamanhoFinal(int tamanhoFinal) {
  this.tamanhoFinal = tamanhoFinal;
 }
        
        
      /**
       * Metodo para testar a forca da senha digitada
       * 
       * @param senha - recebe uma string senha
       * @return forcaSenha - retorna uma constante do objeto Forca
       * @throws tamanho - lanca uma excecao se o tamanho da senha for menor que o valor minimo
       * ou maior que o valor maxio
       * @throws caracter - lanca uma excecao se algum caracter digitado for diferente da regra
       */
 protected Forca testaSenha(String senha) {

  matcher = patter.matcher(senha);
                
                frequencia = 0;
  while (matcher.find()) {

   frequencia++;

  }

  if (senha.length() > tamanhoFinal || senha.length() < tamanhoInicial) {
   
   throw new RuntimeException(this.getExceptionTamanho(tamanhoInicial, tamanhoFinal));

  } else if (senha.length() != frequencia) {

   throw new RuntimeException (this.getExceptionNome() + this.getNome());

  } else {

   desvioPadrao = this.getDesvioPadrao(frequencia, senha);
  }

  if (desvioPadrao <= this.getDesvioPadraoMuitoFraco()) {
   forcaSenha = Forca.MuitoFraca;
  } else if (desvioPadrao > this.getDesvioPadraoMuitoFraco()
    && desvioPadrao <= this.getDesvioPadraoFraco()) {
   forcaSenha = Forca.Fraca;
  } else if (desvioPadrao > this.getDesvioPadraoFraco()
    && desvioPadrao <= this.getDesvioPadraoMedio()) {
   forcaSenha = Forca.Media;
  } else if (desvioPadrao > this.getDesvioPadraoMedio()
    && desvioPadrao <= this.getDesvioPadraoForte()) {
   forcaSenha = Forca.Forte;
  } else if (desvioPadrao > this.getDesvioPadraoForte()) {
   forcaSenha = Forca.MuitoForte;
  }

  return forcaSenha;
 }

Agora temos que importar o Matcher e o Pattern do java.util, que são expressões regulares utilizadas para procurar em uma string os caracteres de um determinado intervalo. Também vamos criar os métodos abstratos, os quais serão responsáveis por obter as informações do objeto que está em questão e a classe enum Forca, para obter as constantes de força da senha.


import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Classe abstrata para medir a forca da senha
 */
public abstract class Senha {
 

       /**
        * Classe enum Forca com as constantes de forca da senha
        */
 public enum Forca {MuitoFraca, Fraca, Media, Forte,MuitoForte }
 

 
 private Forca forcaSenha;
 private Pattern patter = this.getPatter();
 private Matcher matcher;
 private int frequencia;
 private int tamanhoInicial;
 private int tamanhoFinal;
 private Double desvioPadrao;

 public int getTamanhoInicial() {
  return tamanhoInicial;
 }

 public void setTamanhoInicial(int tamanhoInicial) {
  this.tamanhoInicial = tamanhoInicial;
 }

 public int getTamanhoFinal() {
  return tamanhoFinal;
 }

 public void setTamanhoFinal(int tamanhoFinal) {
  this.tamanhoFinal = tamanhoFinal;
 }
        
        
      /**
       * Metodo para testar a forca da senha digitada
       * 
       * @param senha - recebe uma string senha
       * @return forcaSenha - retorna uma constante do objeto Forca
       * @throws tamanho - lanca uma excecao se o tamanho da senha for menor que o valor minimo
       * ou maior que o valor maxio
       * @throws caracter - lanca uma excecao se algum caracter digitado for diferente da regra
       */
 protected Forca testaSenha(String senha) {

  matcher = patter.matcher(senha);
                
                frequencia = 0;
  while (matcher.find()) {

   frequencia++;

  }

  if (senha.length() > tamanhoFinal || senha.length() < tamanhoInicial) {
   
   throw new RuntimeException(this.getExceptionTamanho(tamanhoInicial, tamanhoFinal));

  } else if (senha.length() != frequencia) {

   throw new RuntimeException (this.getExceptionNome() + this.getNome());

  } else {

   desvioPadrao = this.getDesvioPadrao(frequencia, senha);
  }

  if (desvioPadrao <= this.getDesvioPadraoMuitoFraco()) {
   forcaSenha = Forca.MuitoFraca;
  } else if (desvioPadrao > this.getDesvioPadraoMuitoFraco()
    && desvioPadrao <= this.getDesvioPadraoFraco()) {
   forcaSenha = Forca.Fraca;
  } else if (desvioPadrao > this.getDesvioPadraoFraco()
    && desvioPadrao <= this.getDesvioPadraoMedio()) {
   forcaSenha = Forca.Media;
  } else if (desvioPadrao > this.getDesvioPadraoMedio()
    && desvioPadrao <= this.getDesvioPadraoForte()) {
   forcaSenha = Forca.Forte;
  } else if (desvioPadrao > this.getDesvioPadraoForte()) {
   forcaSenha = Forca.MuitoForte;
  }

  return forcaSenha;
 }
        

       /**
        * Metodo abstrato para obter a string, da subclasse, a ser lancada no exception
        * para quando o usuario digita um caracter diferente do definido pela subclasse
        * 
        * @return retorna uma string com a exception
        */

 protected abstract String getExceptionNome();

      /**
        * Metodo abstrato para obter a string, da subclasse, a ser lancada no exception
        * para quando a senha digitada excede o tamanho definido como maximo e minimo
        * 
        * @param tamanhoInicialException - inteiro com o tamanho minimo de caracteres que a 
        * senha deve conter
        * @param tamanhoFinalException - inteiro com o tamanho maximo de caracteres que a senha
        * deve conter
        * @return retorna uma string com a exception
        */

 protected abstract String getExceptionTamanho(int tamanhoInicialException, int tamanhoFinalException);
 
        
      /**
        * Metodo abstrato para obter o calculo do desvio padrao, da subclasse, para verificar 
        * a forca da senha de acordo com os valores definidos pelo programador
        * 
        * @param frequenciDesvioPadrao - inteiro com a quantidade de caracteres digitados
        * na senha
        * @param senha - string com a senha digitada pelo usuario
        * @return retorna um valor double com o calculo do desvio padrao
        */
 protected abstract double getDesvioPadrao(int frequenciaDesvioPadrao, String senha);

        
      /**
        * Metodo abstrato para obter a string, da subclasse, a ser lancada no exception
        * contendo o nome dos caracteres que devem obrigatoriamento compor a senha
        * 
        * @return retorna uma string com o nome dos caracteres
        */
 protected abstract String getNome();
        
        
      /**
        * Metodo abstrato para obter o Pattern, da subclasse, com o intervalo de caracteres
        * que devem compor a senha
        * 
        * @return retorna o pattern com o intervalo de caracteres
        */
 protected abstract Pattern getPatter();
        
        
      /**
        * Metodo abstrato para obter, da subclasse, o valor definido pelo programador 
        * para quando a senha eh muito fraca
        * 
        * @return retorna um double com o valor definido como muito fraco
        */
 protected abstract double getDesvioPadraoMuitoFraco();
        
        
      /**
        * Metodo abstrato para obter, da subclasse, o valor definido pelo programador 
        * para quando a senha eh fraca
        * 
        * @return retorna um double com o valor definido como fraco
        */
 protected abstract double getDesvioPadraoFraco();
        
        
      /**
        * Metodo abstrato para obter, da subclasse, o valor definido pelo programador 
        * para quando a senha eh muito media
        * 
        * @return retorna um double com o valor definido como medio
        */
 protected abstract double getDesvioPadraoMedio();
        
        
      /**
        * Metodo abstrato para obter, da subclasse, o valor definido pelo programador 
        * para quando a senha eh forte
        * 
        * @return retorna um double com o valor definido como muito forte
        */
 protected abstract double getDesvioPadraoForte();
        
        
      /**
        * Metodo abstrato para setar, na subclasse, o valor definido pelo programador 
        * para quando a senha eh muito fraca
        * 
        * @param getDesvioPadraoMuitoFraco - double com o valor que o programador
        * ira definir para o desvio padrao muito fraco
        * @return retorna um double com o valor definido como muito fraco
        */
 protected abstract void setDesvioPadraoMuitoFraco(double getDesvioPadraoMuitoFraco);
        
        
      /**
        * Metodo abstrato para setar, na subclasse, o valor definido pelo programador 
        * para quando a senha eh fraca
        * 
        * @param getDesvioPadraoFraco - double com o valor que o programador
        * ira definir para o desvio padrao fraco
        * @return retorna um double com o valor definido como fraco
        */
 protected abstract void setDesvioPadraoFraco(double getDesvioPadraoFraco);
        
        
      /**
        * Metodo abstrato para setar, na subclasse, o valor definido pelo programador 
        * para quando a senha eh media
        * 
        * @param getDesvioPadraoMedio - double com o valor que o programador
        * ira definir para o desvio padrao medio
        * @return retorna um double com o valor definido como medio
        */
 protected abstract void setDesvioPadraoMedio(double getDesvioPadraoMedio);
        
        
      /**
        * Metodo abstrato para setar, na subclasse, o valor definido pelo programador 
        * para quando a senha eh forte
        * 
        * @param getDesvioPadraoForte - double com o valor que o programador
        * ira definir para o desvio padrao forte
        * @return retorna um double com o valor definido como forte
        */
 protected abstract void setDesvioPadraoForte(double getDesvioPadraoForte);
 

}

Com a nossa super classe criada, agora vamos criar duas subclasses, a senhaCaracteres que será para senha com apenas caracteres (maiúsculo e minúsculo) e a senhaNumeros que será para senha com apenas números.


package componente;

import java.util.regex.Pattern;

public class SenhaCaracter extends Senha {

 private double desvioPadrao;
 private double desvioPadraoForte;
 private double desvioPadraoMedio;
 private double desvioPadraoFraco;
 private double desvioPadraoMuitoFraco;

 @Override
 protected Pattern getPatter() {
  return Pattern.compile(".??[a-zA-Z]");
 }

 @Override
 protected String getNome() {
  return "caracteres minusculos e maiusculos";
 }

 @Override
 protected double getDesvioPadrao(int frequencia, String senha) {

  Estatistica estatistica = new Estatistica();
  
  char[] chars = senha.toCharArray();
  
  estatistica.setArray(chars);  
  desvioPadrao = estatistica.getDesvioPadrao();
  System.out.println(desvioPadrao);
  
  senha = new String(chars);
  
  return desvioPadrao;
 }

 @Override
 protected double getDesvioPadraoMuitoFraco() {
  return desvioPadraoMuitoFraco;
 }

 protected void setDesvioPadraoMuitoFraco(double desvioPadraoMuitoFraco) {
  this.desvioPadraoMuitoFraco = desvioPadraoMuitoFraco;
 }

 @Override
 protected double getDesvioPadraoFraco() {
  return desvioPadraoFraco;
 }

 protected void setDesvioPadraoFraco(double desvioPadraoFraco) {
  this.desvioPadraoFraco = desvioPadraoFraco;
 }

 @Override
 protected double getDesvioPadraoMedio() {
  return desvioPadraoMedio;
 }

 protected void setDesvioPadraoMedio(double desvioPadraoMedio) {
  this.desvioPadraoMedio = desvioPadraoMedio; 
 }

 @Override
 protected double getDesvioPadraoForte() {
  return desvioPadraoForte;
 }

 protected void setDesvioPadraoForte(double desvioPadraoForte) {
  this.desvioPadraoForte = desvioPadraoForte;  
 }

 @Override
 protected String getExceptionNome() {
  return ("A senha deve conter apenas caracteres: ");
 }

 @Override
 protected String getExceptionTamanho(int tamanhoInicial, int tamanhoFinal) {
  return ("A senha deve conter no minimo " + tamanhoInicial
    + " e no maximo " + tamanhoFinal + " caracteres!");
 }
 

 

 
}


package componente;

import java.util.regex.Pattern;


public class SenhaNumeros extends Senha{

 private double desvioPadrao;
 private double desvioPadraoForte;
 private double desvioPadraoMedio;
 private double desvioPadraoFraco;
 private double desvioPadraoMuitoFraco;

 @Override
 protected Pattern getPatter() {
  return Pattern.compile(".??[0-9]");
 }

 @Override
 protected String getNome() {
  return "numeros";
 }

 @Override
 protected double getDesvioPadrao(int frequencia, String senha) {
  
  Estatistica estatistica = new Estatistica();
  
  char[] chars = senha.toCharArray();
  
  estatistica.setArray(chars);  
  desvioPadrao = estatistica.getDesvioPadrao();
  System.out.println(desvioPadrao);
  
  senha = new String(chars);
  
  return desvioPadrao;
 }

 @Override
 protected double getDesvioPadraoMuitoFraco() {
  return desvioPadraoMuitoFraco;
 }

 protected void setDesvioPadraoMuitoFraco(double desvioPadraoMuitoFraco) {
  this.desvioPadraoMuitoFraco = desvioPadraoMuitoFraco;
  
 }

 @Override
 protected double getDesvioPadraoFraco() {
  return desvioPadraoFraco;
 }

 protected void setDesvioPadraoFraco(double desvioPadraoFraco) {
  this.desvioPadraoFraco = desvioPadraoFraco;
 }

 @Override
 protected double getDesvioPadraoMedio() {
  return desvioPadraoMedio;
 }

 protected void setDesvioPadraoMedio(double desvioPadraoMedio) {
  this.desvioPadraoMedio = desvioPadraoMedio; 
 }

 @Override
 protected double getDesvioPadraoForte() {
  return desvioPadraoForte;
 }

 protected void setDesvioPadraoForte(double desvioPadraoForte) {
  this.desvioPadraoForte = desvioPadraoForte;  
 }

 @Override
 protected String getExceptionNome() {
  return ("A senha deve conter apenas caracteres: ");
 }

 @Override
 protected String getExceptionTamanho(int tamanhoInicial, int tamanhoFinal) {
  return ("A senha deve conter no minimo " + tamanhoInicial
    + " e no maximo " + tamanhoFinal + " caracteres!");
 }

 
}


Por último, criaremos a nossa classe Estatistica que terá os métodos para calcular o desvio padrão e a classe Exception.


package componente;

import java.util.Arrays;

public class Estatistica {

 private char array[];

 public double getPearson() {

  return (getDesvioPadrao() / getMediaAritmetica()) * 100;

 }

 public double getMediaAritmetica() {

  double total = 0;

  for (int counter = 0; counter < array.length; counter++)

   total += array[counter];

  return total / array.length;

 }

 public double getSomaDosElementos() {

  double total = 0;

  for (int counter = 0; counter < array.length; counter++)

   total += array[counter];

  return total;

 }

 public double getSomaDosElementosAoQuadrado() {

  double total = 0;

  for (int counter = 0; counter < array.length; counter++)

   total += Math.pow(array[counter], 2);

  return total;

 }

 public double getMediaAritmetica(double array[]) {

  double total = 0;

  for (int counter = 0; counter < array.length; counter++)

   total += array[counter];

  return total / array.length;

 }

 public double getSomaDosElementos(double array[]) {

  double total = 0;

  for (int counter = 0; counter < array.length; counter++)

   total += array[counter];

  return total;

 }

 public void ordenar() {

  Arrays.sort(array);

 }

 public void imprimeArray() {

  System.out.print("\nElementos do Array: ");

  for (int count = 0; count < array.length; count++)

   System.out.print(array[count] + " ");

 }

 public double getVariancia() {

  double p1 = 1 / Double.valueOf(array.length - 1);

  double p2 = getSomaDosElementosAoQuadrado()

  - (Math.pow(getSomaDosElementos(), 2) / Double

  .valueOf(array.length));

  return p1 * p2;

 }

 public double getDesvioPadrao() {

  return Math.sqrt(getVariancia());

 }

 public double getMediana() {

  this.ordenar();

  int tipo = array.length % 2;

  if (tipo == 1) {

   return array[((array.length + 1) / 2) - 1];

  } else {

   int m = array.length / 2;

   return (array[m - 1] + array[m]) / 2;

  }

 }

 public void setArray(char[] array) {

  this.array = array;

 }

}


/**
  * Classe Exception extendendo a classe RuntimeException
*/
public class Exception extends RuntimeException {

 private static final long serialVersionUID = 1L;

 public Exception(String mensagem, Exception e) {
  super(mensagem, e);
 }

 public Exception(String mensagem) {
  super(mensagem);
 }
}

Pronto!! Agora só testar, instanciando e setando o tamanho inicial e final que a senha deve conter e o desvio padrão para a regra do medidor.


package Negocio;

public class Main {


 public static void main(String[] args) {
  
  
  
  String senha = "cA"; 
  
/*  
  
  Senha todos = new SenhaTodosCaracteres();
  Senha numeros = new SenhaNumeros();
  Senha minusculo = new SenhaCaracterMinusculo();
  Senha maiusculo = new SenhaCaracterMaiusculo();
  Senha caracter = new SenhaCaracter();
  Senha caracterEspecial = new SenhaCaracterEspecial();
  
  todos.setTamanhoInicial(2);
  todos.setTamanhoFinal(5);
  
  numeros.setTamanhoInicial(2);
  numeros.setTamanhoFinal(10);
  
  minusculo.setTamanhoInicial(10);
  minusculo.setTamanhoFinal(20);
  
  maiusculo.setTamanhoInicial(20);
  maiusculo.setTamanhoFinal(20);
  
  caracter.setTamanhoInicial(5);
  caracter.setTamanhoFinal(15);
  
  caracterEspecial.setTamanhoInicial(5);
  caracterEspecial.setTamanhoFinal(15);
  
  numeros.setDesvioPadraoMuitoFraco(1);
  numeros.setDesvioPadraoFraco(3);
  numeros.setDesvioPadraoMedio(5);
  numeros.setDesvioPadraoForte(8);
  
    
  System.out.println(numeros.testaSenha(senha));
  System.out.println(minusculo.testaSenha(senha));
  System.out.println(maiusculo.testaSenha(senha));
  System.out.println(caracter.testaSenha(senha));
  System.out.println(caracterEspecial.testaSenha(senha));
    
  
*/ 
  Senha numeros = new SenhaCaracter();
  
  
  numeros.setTamanhoInicial(2);
  numeros.setTamanhoFinal(10);
  numeros.setDesvioPadraoMuitoFraco(1);
  numeros.setDesvioPadraoFraco(3);
  numeros.setDesvioPadraoMedio(5);
  numeros.setDesvioPadraoForte(8);
  
  
  System.out.println(numeros.testaSenha(senha));
 }

}


Nenhum comentário:

Postar um comentário