Atributo para validar Senhas utilizando Data Annotation em Asp.Net MVC 4 com C# (CSharp).

Autor : Antonio Carlos Ferreira de Azevedo
Postado em : 02/06/2016

Data Annotation Custumizado [SenhaBrasil()]

Nesta postagem você vai aprender a validar uma Senha usando Data Annotation e jquery.validate onde será feita a validação tanto do lado do cliente como no servidor.
Vamos criar aqui uma classe derivada da ValidationAttribute e criar nossa classe customizada para a validação no servidor.

SenhaBrasilAttribute

ErrorMessage Mensagem padrão de erro.
SenhaTamanhoMinimo Informe número inteiro que define o tamanho mínimo a ser digitado.
SenhaTamanhoMaximo Informe número inteiro que define o tamanho máximo a ser digitado.
SenhaForteRequerida Informe true se deseja uma senha forte ou seja, será obrigatório digitação no minimo de um carácter maiúsculo, um minusculo e um número.
CaracterEspecialRequerido informe true se deseja que seja obrigatório digitação de pelo menos um carácter especial (@#$%^&+=) valido somente quando SenhaForteRequerida=true.

Crie uma classe na pasta Models em seu projeto MVC com o nome de SenhaBrasilAttribute.cs copie e cole o código abaixo.

SenhaBrasilAttribute.cs

/* 
 * Atributo SenhaBrasil
 * 
 * Data Annotations para Validar uma Senha.
 * 
 * Visite nossa página http://www.codigoexpresso.com.br
 * 
 * by Antonio Azevedo
 *  
 * Chamada em sua Classe : 
 *   [SenhaBrasil(ErrorMessage="Senha Inválida.", SenhaTamanhoMinimo=9, SenhaTamanhoMaximo=9, SenhaForteRequerida=true/false, CaracterEspecialRequerido=true/false )]
 *    
 *    -> SenhaTamanhoMinimo = inteiro com o tamanho minimo exigido para senha (Default = 6)
 *    -> SenhaTamanhoMaximo = inteiro com o tamanho maximo exigido para senha (Default = 12)
 *    -> SenhaForteRequerida = boolean (true/false) (Default=true) Se informado com (true) 
 *       é obrigatorio digitar pelo menos um caracter maiusculo, um minusculo e um numero 
 *    -> CaracterEspecialRequerido = boolean (true/false) (Default=true) Se informado com (true) e SenhaForteRequerida = (true) 
 *       é obrigatorio digitacao de pelo menos um caracter especial ([@#$%^&+=])
 *    
 */
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using System.Web.Mvc;

public class SenhaBrasilAttribute : ValidationAttribute, IClientValidatable
{
    public int SenhaTamanhoMinimo { get; set; }
    public int SenhaTamanhoMaximo { get; set; }

    public Boolean SenhaForteRequerida { get; set; }
    public Boolean CaracterEspecialRequerido { get; set; }
    public SenhaBrasilAttribute()
    {
        this.SenhaTamanhoMinimo = 6;
        this.SenhaTamanhoMaximo = 12;
        this.SenhaForteRequerida = true;
        this.CaracterEspecialRequerido = true;
        this.ErrorMessage = "";     
    }

    protected override ValidationResult IsValid(
        object value,
        ValidationContext validationContext)
    {
        // Carrega mensagem personalizada de erro caso nao tenha sido declarada na chamada do atributo
        if (this.ErrorMessage == "")
        {
            this.ErrorMessage = getMensagemErro();
        }

        // Verifica se o Valor é nulo
        if (value == null)
        {
            value = "";
        }

        string newValue = value.ToString();

        // Verifica se senha não é maior que o tamanho maximo
        if (newValue.Length > this.SenhaTamanhoMaximo)
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }

        // Carrega expressao regular para validação da senha
        Regex regexSenha = new Regex(getRegex());

        // Valida a expressao regular 
        Match match = regexSenha.Match(value.ToString());

        // Se valida retorna com sucesso
        if (match.Success)
        {
            return ValidationResult.Success; ;
        }

        // Devolve o erro padrao se a expressao nao for valida.
        return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
    }

    // Diretivas para validação do lado do Cliente, implementa com jquery.validate
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
        ModelMetadata metadata,
        ControllerContext context)
    {
        // Carrega mensagem personalizada de erro caso nao tenha sido declarada na chamada do atributo
        if (this.ErrorMessage == "")
        {
            this.ErrorMessage = getMensagemErro();
        }

        var Rule = new ModelClientValidationRule
        {
            ValidationType = "senhabrasil",
            ErrorMessage = this.FormatErrorMessage(metadata.PropertyName)
        };

        // Carrega parametros para JQuery
        string[] array = new string[] { getRegex(), this.SenhaTamanhoMaximo.ToString() };

        Rule.ValidationParameters["params"] =  string.Join(";", Array.ConvertAll(array, x => x.ToString()));

        yield return Rule;
    }

    /// <summary>
    /// Retorna expressao regular de acordo com parametros informados no atributo
    /// </summary>
    private string getRegex()
    {
        string regex = "^.*(?=.{" + this.SenhaTamanhoMinimo.ToString() + ","+this.SenhaTamanhoMaximo.ToString()+"})";

      
        if (SenhaForteRequerida)
        {
            regex += "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])";
            if (this.CaracterEspecialRequerido)
            {
                regex += "(?=.*[@#$%^&+=])";
            }
        }
        else
        {
            regex += "(?=.*[a-zA-Z0-9@#$%^&+=])";
        }

        regex += ".*$";

        return regex;
    }

    /// <summary>
    /// Retorna mensagem de erro de acordo com parametros informados no atributo
    /// </summary>
    private string getMensagemErro()
    {
        string mErro = "Senha " + this.SenhaTamanhoMinimo.ToString();

        if (this.SenhaTamanhoMaximo != this.SenhaTamanhoMinimo)
        {
          mErro += " a " + this.SenhaTamanhoMaximo.ToString();
        }

        mErro += " caracteres";

        if (this.SenhaForteRequerida)
        {
            mErro += ", Conter Letras maiusculas, minusculas";

            if(CaracterEspecialRequerido)
            {
                mErro += ", caracteres especiais";
            }

            mErro += " e números";
        }

        mErro += ".";

        return mErro;
    }
}

Agora vamos cuidar da validação do lado no cliente, ou seja, no navegado do cliente.
O MVC se encarrega de transportar os parâmetros para nosso HTML mas mesmo assim temos que fazer toda a validação em JavaScript novamente.

Crie uma arquivo JavaScript na pasta Scripts de seu projeto MVC, de o nome de CustomValidacoes.js copie e cole o código abaixo.

CustomValidacoes.js

// Aqui adicionamos os metodos respeitando os nomes gerado em nossa classe atributo
// os nomes devem estar em caixa baixa tanto na integração como aqui no JavaScript (Nome atributo, parametro)
$.validator.unobtrusive.adapters.addSingleVal('senhabrasil', 'params');

//Aqui temos a funcao que Valida do lado do cliente a senha digitadas utilizando uma expressão regular
$.validator.addMethod('senhabrasil',
function (value, element, params) {

   // Separamos os parametros recebidos
   var parametros = params.split(';');

   // Definimos o tamanho maximo com base em parametro recebido      
   var maximo = parametros[1].toString();

   // Verifica se o tamanho maximo foi atingido
    if (value.length > maximo) {
           return false;
    }
   

    // Recupera expressao regular com base em parametro recebido
    var expReg = parametros[0];
    
    // Valida Expressao
    var result = value.match(expReg);

    // Retorna false caso a expressao nao seja valida
    if (result != null) {
        return true;
    }

    return false;
});

Este arquivo deve ser carregado após o carregamento do jquery.validate.

Exemplo de como utilizar o atributo em sua classe.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using SeuProjeto.Models;

namespace AspNetMVC_Aula.Models
{
    public class ModAluno
    {
     [SenhaBrasil(CaracterEspecialRequerido=true, SenhaForteRequerida=true, SenhaTamanhoMinimo=5)]
     public string Senha { get; set; }
    }
}







Comentários