ASP .NET -  Acesso remoto ao MySQL e cifrando e decifrando senhas - I

 No artigo de hoje vamos criar uma aplicação ASP .NET Web Forms para acessar os dados de um banco de dados MySQL remotamente mostrando como podemos cifrar e decifrar senhas de usuários e também vamos implementar uma verificação de palavras proibidas impedindo que o usuário use termos não apropriados.

Na figura abaixo vemos a nossa aplicação ASP .NET onde o usuário vai informar o nome do usuário e uma senha e ao submeter sua requisição a senha será cifrada e exibida em um controle GridView.

Note que estamos obtendo e exibindo o endereço IP do visitante e também estamos realizando uma verificação de palavras proibidas de forma a impedir que o usuário informe termos impróprios no nome do usuário e na senha. Este é um recurso muito usado em sites para evitar pessoas mal educadas.

Recursos usados

Objetivos

Aprendizado

Definindo o Banco de dados e a tabela no MySQL

Neste exemplo eu vou usar o meu banco de dados MySQL hospedado em meu servidor de hospedagem. Vou criar uma tabela chamada usuários usando a ferramenta phpMyAdmin.

Abaixo temos a estrutura da minha tabela Usuarios criada no phpMyAdmin:

Nota: Da mesma forma podemos usar o MySQL instalado na máquina local o que vai mudar são as permissões e a string de conexão.

Nossa tabela Usuarios possui 3 campos:

Para realizar a conexão com meu banco de dados remoto eu preciso das seguintes informações:

A string de conexão que deverá ser montada tem a seguinte estrutura:

String stringConexao = "Database=" + BANCO + ";Data Source=" + HOST + ";User Id=" + USUARIO + ";Password=" + SENHA + "; pooling=false";

Com essas informações podemos  criar o projeto ASP .NET no Visual Studio.

Criando a aplicação ASP .NET Web Forms

Abra o Visual Studio 2012 Express for web e clique em New Project;

A seguir selecione o template Visual C# -> Web -> ASP .NET Empty Web Application e informe o nome ASPNET_MySQL_CifraDecifra e clique em OK;

Agora vamos incluir um WebForm no projeto que será a nossa página principal.

No menu PROJECT clique em Add New Item e selecione o template Web Form informando o nome Default.aspx e clicando no botão Add;

Abra a página Default.aspx, selecione o modo Design e a partir da ToolBox inclua o seguintes controles:

Defina os controles na página conforme o leiaute abaixo:

Vamos configurar o nosso GridView definindo as colunas, o estilo do cabeçalho e das linhas e o evento OnRowDataBound() conforme o código a seguir:

<asp:GridView ID="gdvUsuarios" runat="server" AutoGenerateColumns="false" HeaderStyle-BackColor="#3AC0F2"
    HeaderStyle-ForeColor="White" RowStyle-BackColor="#A2DEE2" OnRowDataBound = "OnRowDataBound" Width="411px">
    <Columns>
        <asp:BoundField DataField="Usuario" HeaderText="Usuário" />
        <asp:BoundField DataField="Senha" HeaderText="Senha Cifrada" />
        <asp:BoundField DataField="Senha" HeaderText="Senha Decifrada" />
    </Columns>
<HeaderStyle BackColor="#3AC0F2" ForeColor="White"></HeaderStyle>
<RowStyle BackColor="#A2DEE2"></RowStyle>
</asp:GridView>

O método OnRowDataBound() gera o evento RowDataBound.

Antes do controle GridView poder ser processado, cada linha no controle deve ser vinculada à um registro na fonte de dados. O evento RowDataBound é disparado quando uma linha de dados (representada por um objeto GridViewRow) é vinculada aos dados no controle GridView. Isso permite que você forneça um método de manipulação de eventos, que executa uma rotina personalizada, tais como modificar os valores dos dados vinculados à linha, sempre que esse evento ocorrer.

Estamos usando esse evento para chamar uma rotina que decifra a senha exibida em uma linha do GridView.

Criando as classes para acesso a dados , criptografia e verificação de palavras proibidas

Embora a aplicação seja  muito simples e eu poderia incluir todo o código na página Default.aspx mas como queremos estar aderentes às boas práticas vamos separar o código responsável pela conexão com banco de dados, pela cifragem e decifragem da senha e pela verificação das palavras proibidas em classes. Assim iremos criar 3 classes em nosso projeto:

  1. Conexao.cs - responsável pelo acesso aos dados da aplicação
  2. Cripto.cs - responsável por realizar a cifragem e decifragem das senhas
  3. Censura.cs - responsável por definir e verificar as palavras proibidas

Agindo assim teremos uma interface limpa e vamos facilitar a manutenção da nossa aplicação pois qualquer alteração em uma das funcionalidades deverá ser feita de forma mais simples. Assim, por exemplo, se houver alteração em uma funcionalidade de acesso a dados as outras partes da aplicação não serão afetadas.

Antes de prosseguirmos temos que incluir uma referência ao MySQL Connector/Net. Para isso você primeiro tem que fazer o download do componente na página - http://dev.mysql.com/downloads/connector/net/ - e descompactar na sua máquina.

A seguir no menu PROJECT clique em Add Reference e a seguir selecione a guia Browse e localize e marque o item MySql.Data.dll conforme mostrado abaixo:

1- Criando a classe Conexao.cs

No PROJECT clique em Add Class e a seguir informe o nome Conexao.cs. e digite o código abaixo neste arquivo:

using System;
using MySql.Data.MySqlClient;
using System.Data;
namespace ASPNET_MySQL_CifraDecifra
{
    public class Conexao
    {
        public static string GetStringConexao()
        {
            try
            {
                //Informe aqui os dados de acesso ao banco [IMPORTANTE]
                String HOST = "999.99.99.999";
                String USUARIO = "seu usuario";
                String SENHA = "sua senha";
                String BANCO = "seu banco";
                //Monta a string de conexão utilizando os dados informados anteriormente
                String stringConexao = "Database=" + BANCO + ";Data Source=" + HOST + ";User Id=" + USUARIO + ";Password="    
 + SENHA + "; pooling=false";
                return stringConexao;
            }
            catch (Exception ex)    
            {
                throw ex;
            }
        }
        public static MySqlConnection AbreConexao()
        {
            try
            {
                MySqlConnection con = new MySqlConnection(Conexao.GetStringConexao());
                con.Open();
                return con;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static void FechaConexao(MySqlConnection cn)
        {
            try
            {
                cn.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static DataTable ExecutaComando(string comando, MySqlConnection con)
        {
            try
            {
                MySqlCommand cmd = new MySqlCommand(comando);
                MySqlDataAdapter da = new MySqlDataAdapter();
                DataTable dt = new DataTable();
                cmd.CommandType = CommandType.Text;
                cmd.Connection = con;
                da.SelectCommand = cmd;
                da.Fill(dt);
                return dt;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                FechaConexao(con);
            }
        }
        public static void ExecutaComando(string comando, MySqlConnection con, Usuario usuario)
        {
            try
            {
                MySqlCommand cmd = new MySqlCommand(comando);
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.AddWithValue("@Usuario", usuario.Nome);
                cmd.Parameters.AddWithValue("@Senha", Cripto.Cifra(usuario.Senha));
                cmd.Connection = con;
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                FechaConexao(con);
            }
        }
    }
}

Na classe Conexao a utilização do namespace MySql.Data.MySqlClient e a definição dos métodos:

2- Criando a classe Cripto.cs

No PROJECT clique em Add Class e a seguir informe o nome Cripto.cs e digite o código abaixo neste arquivo:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace ASPNET_MySQL_CifraDecifra
{
    public class Cripto
    {
        public static string Cifra(string textoPuro)
        {
            string chaveEncriptacao = "MAC2014SJRP";
            byte[] bytesLimpos = Encoding.Unicode.GetBytes(textoPuro);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(chaveEncriptacao, new byte[] 
{ 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))       
                    {
                        cs.Write(bytesLimpos, 0, bytesLimpos.Length);
                        cs.Close();
                    }
                    textoPuro = Convert.ToBase64String(ms.ToArray());
                }
            }
            return textoPuro;
        }
        public static string Decifra(string textoCifrado)
        {
            string chaveEncriptacao = "MAC2014SJRP";
            byte[] bytesCifrados = Convert.FromBase64String(textoCifrado);
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(chaveEncriptacao, new byte[] 
{ 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesCifrados, 0, bytesCifrados.Length);
                        cs.Close();
                    }
                    textoCifrado = Encoding.Unicode.GetString(ms.ToArray());
                }
            }
            return textoCifrado;
        }
    }
}

Na classe Cripto usamos os recursos do namespace System.Security.Cryptography e definimos dois métodos:

Usamos a classe Rfc2898DeriveBytes que implementa a funcionalidade de derivação da chave baseada na senha, PBKDF2(Password-Based Key Derivation Function 2), passando gerador de número pseudo randômico baseado em HMACSHA1(Calcula um HMAC usando uma função hash SHA1)

A classe Rfc2898DeriveBytes usa uma senha, um salt e uma contagem de iteração e, em seguida, gera chaves por meio de chamadas para o método GetBytes.

3- Criando a classe Censura.cs

No PROJECT clique em Add Class e a seguir informe o nome Censura.cs e digite o código abaixo neste arquivo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
namespace ASPNET_MySQL_CifraDecifra
{
    public class Censura
    {
              /// <summary>
	/// carrega as palavras proibidas de um arquivo XML
	/// em uma lista genérica (List(T)
	/// </summary>
	/// <param name="arquivo">O nome do arquivo que trata as palavras proibidas</param>
    	/// <returns></returns>
             public static List<string> ListaPalavrasProibidas(string arquivo)
     	{
	        //cria uma nova lista para tratar as palavras proibidas
	        List<string> palavras = new List<string>();
	        //cria um novo XmlDocument, para ler o arquivo XML
	        XmlDocument xmlDoc = new XmlDocument();
	        //Usando SelectNodes vamos passar a consulta XPath
	        //de forma a poder navegar através dos nós XML do arquivo
	        string consulta = "/ListaPalavras/palavra";
	        //carrega documento XML
	        xmlDoc.Load(arquivo);
	        //percorre todos os XmlNodes e verifica o criterio XPath
                    foreach (XmlNode node in xmlDoc.SelectNodes(consulta))
	        {
	            //inclui um InnerText de cada ChildNodes encontrado
	            palavras.Add(node.ChildNodes[0].InnerText);
	        }
	        //retorna a lista preenchida List(T)
	        return palavras;
	   }

             /// <summary>
    	/// Determina se uma palavra esta na lista de palavras proibidas
    	/// </summary>
    	/// <param name="palavra">a palavra a ser verificada</param>
    	/// <param name="arquivo">o nome do arquivo com as palavras proibidas</param>
    	/// <returns></returns>
    	public static bool IsPalavraProibida(string palavra,string arquivo)
    	{
                     //cria uma nova lista List(T) para tratar as palavras. 
                     //Preenche a lista chamando o método ListaPalavrasProibidas 
	        List<string> palavrasProibidas = Censura.ListaPalavrasProibidas(arquivo);
	        //percorre a lista 
	        for (int i = 0; i < palavrasProibidas.Count; i++)
	        {
  	            //em cada iteração comparamos a palavra com a lista
                        //se encontrar retorna true
	            if (palavra.ToLower() == palavrasProibidas[i].ToLower()) return true;
	        }
	        //se não encontrar retorna false
	        return false;
    	}
       }
}

Na classe Censura vamos usar os recursos do Generics e do XML da plataforma .NET. Nesta classe definimos dois métodos:

Para criar o arquivo XML -  ListaPalavrasProibidas.xml - podemos usar os recursos do Visual Studio.

Clique no menu PROJECT e a seguir em Add New Item;

A seguir clique em Visual C# -> XML File e informe o nome  ListaPalavrasProibidas.xml e clique em Add;

Nosso arquivo XML terá a seguinte estrutura:

Observe que temos o nó Raiz - <ListaPalavras> e os nós filhos <palavra>. Usamos essa hierarquia para navegar no arquivo XML, carregar os dados do arquivo e realizar pesquisas também.

Para concluir a primeira parte deste artigo vamos criar uma classe Usuario com as propriedades Nome e Senha que representa um usuário do sistema.

No PROJECT clique em Add Class e a seguir informe o nome Usuario.cs e digite o código abaixo neste arquivo:

namespace ASPNET_MySQL_CifraDecifra
{
    public class Usuario
    {
        public string Nome { get; set; }
        public string Senha { get; set; } 
    }
}

Esta classe iremos usar para transferir os dados entre as classes e a camada de apresentação.

Em todas as classes os métodos foram definidos como estáticos (static) de forma a podermos chamá-los sem ter que criar uma instância das classes.

Na segunda parte do artigo iremos implementar as funcionalidades da aplicação ASP .NET usando os recursos criados. 

Tito 3:10 Ao homem faccioso, depois da primeira e segunda admoestação, evita-o,

Tito 3:11 sabendo que esse tal está pervertido, e vive pecando, e já por si mesmo está condenado.

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

 

             Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter
 

Referências:


José Carlos Macoratti