Avaliação do Usuário

Estrela ativaEstrela ativaEstrela ativaEstrela ativaEstrela ativa
 

 

ACOMPANHE A SÉRIE

Sistema de Login e Senha no Access/VBA - Parte 1/5
Sistema de Login e Senha no Access/VBA - Parte 2/5
Sistema de Login e Senha no Access/VBA - Parte 3/5
Sistema de Login e Senha no Access/VBA - Parte 4/5
Sistema de Login e Senha no Access/VBA - Parte 5/5

EXEMPLO DO ARTIGO

Faça o download do exemplo do artigo para estudo: LoginSeguro.zip

DICA IMPORTANTE PARA ELEVAR SEU CONHECIMENTO

Assista as vídeo-aulas do Curso de Access 2010 (OfficeGuru) e também as do Curso de Programação em Access/VBA.
Para os leigos o Curso de Programação em Access/VBA é obrigatório.


INTRODUÇÃO

De nada adianta um desenvolvedor se preocupar em deixar seu sistema bem apresentado, com telas bem desenhadas e cheias de estilo, se o aplicativo não apresenta o mínimo de segurança no momento de realizar a verificação de identifidade do usuário. Garantir o acesso somente a quem possui tal direito é uma tarefa crucial nos sistemas informatizados.

Com a quinta e última parte da série de artigos, chegamos ao final desta pequena jornada que apresenta ao leitor os conceitos mínimos de funcionalidade e segurança em um sistema que implementa um esquema básico de Login e Senha utilizando Access e VBA.

Nesta etapa abordaremos a validação de senhas fortes e procedimentos de prevenção contra ataques ao sistema, além de proteger os dados para o caso de uma invasão bem sucedida.

OBSERVAÇÕES IMPORTANTES

Gostaria, antes, de deixar claro que serão apresentados apenas os conceitos básicos de segurança e as principais técnicas. De modo algum este artigo pode ser tomado como referência para implantação de um sistema a prova de falhas, já que isto envolve uma gama infinita de procedimentos e conhecimento extremamente avançado.

Além disso, não serão abordados outros aspectos referentes à segurança do sistema. Caso queira complementar seus estudos pesquise sobre criação de MDE/ACCDE, bloqueio de tecla Shift, senha do editor do VBA, criptografia da senha do banco de dados Access, execução em modo Runtime, acesso ao banco de dados via linha de código e transporte de senhas entre Front-end e Back-end, em modo claro, via rede de computadores.

Neste artigo vamos tratar apenas de alguns procedimentos que envolvem o sistema de login e senha, exclusivamente. Vamos a eles.

OPÇÕES DE APLICATIVO

O Access, assim como o restante dos aplicativos Office, possui uma série de opções internas que definem o modo como os dados são tratados. Para que nossa implementação de segurança funcione corretamente, sem que ocorram armadilhas durante a digitação ou a comparação de senhas pelo usuário, vamos incluir algumas instruções em nosso código.

Primeiro, para que a comparação entre senhas ocorra em modo binário e não em modo texto, inclua, ou altere caso já esteja configurada, a seguinte opção nos módulos de código:

Option Compare Binary

A opção de comparação do tipo binário evita que o VBA compare duas strings de texto em modo case insensitive, que é o padrão para aplicativos Windows. Assim as senhas "ABcd123#" e "aBcd123#" serão diferentes. Caso o módulo onde se encontra a função de comparação esteja, por exemplo, com a opção de comparação do tipo Database, as senhas seriam consideradas iguais.

Agora sim, podemos partir para a batalha de verdade.

PROCEDIMENTOS DE SEGURANÇA: SENHAS FORTES

Em primeiro lugar, temos que impedir que o usuário faça o que ele mais gosta de fazer na hora de cadastrar senhas: utilizar senhas fracas!

Sim, é a mais pura verdade. Devido à comodidade, grande parte dos usuários não se preocupam em seguir as regras tão divulgadas sobre os tipos de senha que devem ser evitadas. Utilizar o próprio nome, data de nascimento, palavras que se encontram em dicionários de ataque de hackers e crackers, entre outros, são atitudes que trazem o nível de segurança para próximo do nada.

Então devemos começar a implantar a segurança das senhas utilizando uma função que verifica se ela é ou não uma senha forte.

Crie um novo módulo, chamado FuncoesSeguranca e inclua a função forcaSenha(), abaixo.

Option Compare Binary
Option Explicit
Function forcaSenha(argSenha As String) As Integer
'================================================================
'Função forcaSenha()
'
'Verifica se uma senha é segura com base nos parâmetros passados,
'levando em consideração tamanho da senha, presença de letras
'minúsculas e maiúsculas, números, símbolos e repetições.
'
'Valores de resultado (0 a 100):
' >= 0  e < 20  --> Senha Muito Fraca
' >= 20 e < 50  --> Senha Fraca
' >= 50 e < 80  --> Senha Média
' >= 80 e < 90  --> Senha Forte
' >= 90 e < 100 --> Senha Muito Forte
' = 100         --> Senha Fortíssima
'
'Autor: Plinio Mabesi
'Fevereiro 2012
'pliniomabesi@gmail.com
'www.mabesi.com
'================================================================
    'Declaração de variáveis
    Dim i As Integer, j As Integer
    Dim caracteresRepetidos As Integer
    Dim strMinusculas As String, strMaiusculas As String
    Dim strNumeros As String, strSimbolos As String
    Dim contemMaiuscula As Boolean, contemMinuscula As Boolean
    Dim contemNumero As Boolean, contemSimbolo As Boolean
    Dim tamanhoSenha As Integer
   
    'Letras, síbolos e números
    strMinusculas = "abcdefghijklmnopqrstuvwxyz"
    strMaiusculas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    strSimbolos = """!@#$%¨&;*()-_=+`´[]{}§£¢ªº^~<>,.:/?\| "
    strNumeros = "0123456789"
   
    'Obtem o tamanho da senha
    tamanhoSenha = Len(argSenha)
   
    'Atribui pontuação imediata
    'para senhas muito curtas
    If tamanhoSenha = 0 Then
      forcaSenha = 0
      Exit Function
    ElseIf tamanhoSenha = 1 Then
      forcaSenha = 4
      Exit Function
    End If
   
    'Obtem a pontuação da senha pelo seu tamanho
    '0 a 70 pontos ( >=12 --> 70 pt )
    If tamanhoSenha < 12 Then
      forcaSenha = ((tamanhoSenha * tamanhoSenha) / 144) * 70
    Else
      forcaSenha = 70
    End If
   
    'Verifica se contém letras minúsculas
    For i = 1 To tamanhoSenha
        If InStr(1, strMinusculas, Mid(argSenha, i, 1)) > 0 Then
            contemMinuscula = True
        End If
    Next i
   
    'Verifica se contem letras maiúsculas
    For i = 1 To tamanhoSenha
        If InStr(1, strMaiusculas, Mid(argSenha, i, 1)) > 0 Then
            contemMaiuscula = True
        End If
    Next i
   
    'Verifica se contem números
      For i = 1 To tamanhoSenha
          If InStr(1, strNumeros, Mid(argSenha, i, 1)) > 0 Then
              contemNumero = True
          End If
      Next i
   
    'Verifica se contem símbolos
      For i = 1 To tamanhoSenha
          If InStr(1, strSimbolos, Mid(argSenha, i, 1)) > 0 Then
              contemSimbolo = True
          End If
      Next i
     
      'Soma 10 pontos caso a senha contenha
      'letras minúsculas e maiúsculas
      If contemMinuscula And contemMaiuscula Then
        forcaSenha = forcaSenha + 10
      ElseIf contemMinuscula Or contemMaiuscula Then
        forcaSenha = forcaSenha + 4
      End If
     
      If contemNumero Then
        forcaSenha = forcaSenha + 10
      End If
     
      If contemSimbolo Then
        forcaSenha = forcaSenha + 10
      End If
     
      'Verifica se há caracteres repetidos
      'e deduz pontos proporcionalmente
      caracteresRepetidos = 0
      For i = 1 To tamanhoSenha
          For j = i + 1 To tamanhoSenha
              If Mid(argSenha, i, 1) = Mid(argSenha, j, 1) Then
                  caracteresRepetidos = caracteresRepetidos + 1
                  Exit For
              End If
          Next j
      Next i
     
      'Resultado do cálculo de força de senha
      forcaSenha = forcaSenha - (caracteresRepetidos * 2)
End Function

Conforme você pode ver nos comentários, esta função verifica se a senha possui o tamanho mínimo recomendado, além de testar a existência de diferentes caracteres, como letras minúsculas e maiúsculas, números e símbolos. A função testa, ainda, se a senha não possui caracteres repetidos e calcula a quantidade de repetições.

Conforme a senha contenha ou não os elementos pesquisados, a pontuação é atribuída a cada item avaliado, chegando-se, ao final, a um resultado que está compreendido entre 0 e 100, sendo 0 uma senha totalmente insegura (na verdade inexistente) e 100 uma senha extremamente forte, que oferece grande dificuldade para ser quebrada por ataques força bruta.

Perceba que, além da opção de comparação incluímos a opção Explicit, que nos obriga a declarar variáveis.


Piscando Dica: Option Explicit: Além da opção de comparação, sobre a qual comentamos anteriormente, acostume-se a utilizar a opção Explicit , que tem a finalidade de obrigá-lo a declarar suas variáveis antes de utilizá-las.

Este procedimento não é obrigatório, mas evita diversos erros que ocorrem devido à dispersão de variáveis pelo código, quando estamos trabalhando com variáveis não declaradas.



EXIGINDO UMA SENHA FORTE

Agora que podemos calcular a força de uma senha devemos definir um valor mínimo e obrigar o usuário a escolher uma senha que atenda a estes requisitos. Vamos alterar o código do evento Ao Clicar do botao btnAlterar, no formulário FAlterarSenha, para exigir o nível mínimo definido pelo administrador do sistema.

Para exemplo, em nosso projeto, vamos supor que uma força de senha igual a 50 seja suficiente, considerando uma necessidade de segurança média. Vejamos como ficaria o código:

Private Sub btnAlterar_Click()

  If IsNull(txtSenhaAtual) Then
  
    MsgBox "Informe a senha atual.", vbExclamation, "Alterar Senha"
    txtSenhaAtual.SetFocus
    
  ElseIf Not verificaLogin(txtLogin, txtSenhaAtual) Then
  
    MsgBox "Senha atual incorreta. Por favor, tente novamente.", _
            vbExclamation, "Alterar Senha"
    txtSenhaAtual.SetFocus
    
  ElseIf IsNull(txtNovaSenha) Then
  
    MsgBox "Informe a nova senha.", vbExclamation, "Alterar Senha"
    txtNovaSenha.SetFocus
    
  ElseIf txtNovaSenha = txtSenhaAtual Then
  
    MsgBox "A nova senha deve ser diferente da atual.", _
            vbExclamation, "Alterar Senha"
    txtNovaSenha.SetFocus
    
  ElseIf txtNovaSenha = txtLogin Then
  
    MsgBox "A nova senha deve ser diferente do seu login.", _
            vbExclamation, "Alterar Senha"
    txtNovaSenha.SetFocus
    
  ElseIf InStr(txtNovaSenha, "'") > 0 Then
  
    MsgBox "A nova senha não pode conter aspas simples.", _
            vbExclamation, "Alterar Senha"
    txtNovaSenha.SetFocus
    
  ElseIf InStr(txtNovaSenha, ";") > 0 Then
  
    MsgBox "A nova senha não pode conter o caracter ponto e vírgula.", _
            vbExclamation, "Alterar Senha"
    txtNovaSenha.SetFocus
    
  ElseIf txtNovaSenha = getSenhaPadrao Then
  
    MsgBox "Nova senha inválida. Por favor, insira uma nova senha diferente.", _
            vbExclamation, "Alterar Senha"
    txtNovaSenha.SetFocus
    
  ElseIf IsNull(txtConfirmaSenha) Then
  
    MsgBox "Confirme a nova senha.", vbExclamation, "Alterar Senha"
    txtSenhaAtual.SetFocus
    
  ElseIf txtConfirmaSenha <> txtNovaSenha Then
  
    MsgBox "Confirmação de senha incorreta. Por favor, tente novamente.", _
            vbExclamation, "Alterar Senha"
    txtConfirmaSenha.SetFocus
    
  Else
    
    'Testando a força da senha do usuário
    'para necessidade de segurança média.
    If forcaSenha(txtNovaSenha) >= 50 Then
      alterarSenha txtLogin, txtNovaSenha
      MsgBox "Senha Alterada com sucesso.", vbInformation, "Alterar Senha"
      DoCmd.Close
    Else
      MsgBox "A senha escolhida não atende aos requisitos de segurança." & vbCrLf _
            & vbLf & _
            "Por favor, utilize letras maiúsculas e minúsculas, além" & vbCrLf & _
            "de números e símbolos para criar uma senha forte." & vbCrLf _
            & vbLf & _
            "O tamanho mínimo recomendado é de 8 caracteres." _
            , vbExclamation, "Senha Insegura"
    End If
    
  End If
  
End Sub

Faça o teste, alterando a senha do usuário criado por senhas de diversas combinações, tanto fracas como fortes. Veja o resultado.


PROCEDIMENTOS DE SEGURANÇA: SQL INJECTION

Você já ouviu falar em SQL Injection? Não! Então fique atento, pois a segurança de diversos sistemas já foi quebrada com a simples utilização dos recursos da linguagem SQL, que é a base para a manipulação de informações armazenadas em bancos de dados.

Em nosso projeto utilizamos a função DCount() para buscar, na tabela Usuario, o regisro que corresponda ao critério especificado. O critério a que estamos nos referindo foi montado utilizando-se um esquema que nada mais é do que uma cláusula Where da linguagem SQL. A função DCount() apenas encapsula uma consulta SQL para facilitar o nosso acesso ao banco de dados.

Assim sendo, estamos sujeitos, como em qualquer outro sistema, às regras da linguagem SQL. Vamos, então, analisar algumas delas:

  1. Os critérios são formados pelo nome do campo da tabela, um operador e um ou mais valores de comparação;
  2. Os valores de comparação do tipo texto devem estar entre aspas simples;
  3. Os valores de data devem estar no formato americano, envolvidos pelo caracter cerquilha - #mm/dd/yyy# -, onde mm corresponde ao número do mês, com 2 dígitos, dd ao  número do dia, com 2 dígitos e yyyy ao ano, com 4 dígitos;
  4. Os carateres curinga podem ser usados em pesquisa para encontrar partes de valores de texto;
  5. Vários critérios podem ser combinados utilizando-se os operadores lógicos OR e AND;
  6. As combinações entre parênteses tem precedência. Quanto mais interna a combinação maior a sua precedência em relação às demais;
  7. Funções podem ser utilizadas em expressões de critério;
  8. O sinal de ponto e vírgula (;) finaliza uma expressão SQL;
  9. Strings de texto vazias são aceitas normalmente como valor de critério.

Existem diversas outras regras, porém o conhecimento destas regras é suficiente para nosso propósito.

Veja alguns exemplos de critérios de pesquisa:

/** Nome do cliente igual a Pedro: */
nomeCliente = 'Pedro'
 
/** Nome do cliente igual a Pedro e data da venda após 10/02/2012: */
nomeCliente = 'Pedro' AND dataVenda > #02/10/2012#
 
/** Idade do funcionário entre 25 e 30 anos e ano de contratação igual a 2008: */
idadeFunc Between 25 AND 30 AND Year(dataContratacao)=2008

/** Nome do cliente contendo o trecho 'mar' (Retorna Itamar, Maria, Marcio, etc...): */
nomeCliente Like '*mar*'

Perceba que em todos os casos precisamos obter um critério que seja verdadeiro para que os resultados sejam retornados. Ou seja, precisamos de um valor True para que o critério seja atendido.

Então, partindo deste princípio, qual seria o resultado final da expressão abaixo, mesmo que o nome do cliente não correspondesse ao valor informado?

nomeCliente = 'Pedro' OR 1 = 1

Seria True, pois a expressão 1 = 1 será sempre verdadeira, concorda? Então continuemos com o raciocínio.

Vamos analisar, agora, o critério formado pela função verficaLogin():

Function verificaLogin(argLogin As String, argSenha As String) As Boolean

    Dim criterio As String
    
    criterio = "login='" & argLogin & "' And senha='" & argSenha & "'"
    
    If Nz(DCount("login", "Usuario", criterio), 0) > 0 Then
        verificaLogin = True
        setUsuarioAtual argLogin
    Else
        verificaLogin = False
    End If

End Function

Supondo que o nome do usuário seja "mabesi" e a senha seja "123456", a expressão de critério SQL ficaria assim:

login='mabesi' And senha='123456'

Desta maneira, caso um usuário mal-intencionado simplesmente entre com o login "mabesi" e a senha "654321", por exemplo, a expressão de critério não irá corresponder ao dado armazenado na tabela, e irá retornar False como resultado. Assim a função DCount() retornará o valor 0, pois não encontrará nenhum registro que atenda ao critério.

Mas, porém, contudo, todavia, entretanto, imagine que este usuário seja um Cracker e informe o login "mabesi" e como senha o seguinte texto:

' OR ''='

Faça o teste em seu sistema e veja o que acontece. Mas faça o teste com o seu usuário do grupo Administradores.

O atacante conseguiu acesso de administrador em seu sistema, não foi? Por que isto aconteceu, mesmo sem ele haver informado a senha correta?

Muito simples. Veja como ficou a expressão de critério SQL gerada pela função verificaLogin():

login='mabesi' And senha='' OR ''=''

Veja que a última parte da expressão, após o operador lógio OR, sempre retornará o valor True, pois uma string vazia sempre será igual a outra string vazia.

Pois bem, esta é a técnica conhecida como SQL Injection, ou Injeção de SQL. Existem diversas outras técnicas de ataque, além desta que aprendemos agora. A boa notícia é que também há diversas técnicas para prevenir estes ataques.

Em nosso projeto vamos criar uma função simples para realizar uma limpeza nas variáveis de login e senha, a fim de evitar que este tipo de código malicioso comprometa a segurança do sistema.

No módulo FuncoesSeguranca cria a função limparSenha(), com o seguinte código:

Function limparSenha(argExpressao As String) As String

  'Retirando as aspas simples
  limparSenha = Replace(argExpressao, "'", "")
  
  'Retirando os sinais de ponto e vírgula
  limparSenha = Replace(argExpressao, ";", "")
  
End Function

Conforme explicado anteriormente, esta é uma função bem simples, cuja única finalidade é retirar todas as aspas simples e os sinais de ponto e vírgula que estejam presentes no texto recebido como parâmetro, devolvendo um novo texto, já com a limpeza efetuada. Apenas esta tarefa já é suficiente para evitar o ataque exemplificado. Além disso evita que ocorram erros, já que o sinal ; encerra uma expressão SQL e, neste caso, não queremos que isto ocorra.

Agora, para que a limpeza tenha efeito em nosso sistema, devemos alterar o código do evento Ao Clicar do botão btnLogin, no formulário FLogin. Ele deve ficar da seguinte forma:

Private Sub btnLogin_Click()

  Dim strSenha As String

  If IsNull(cbxLogin) Then
    MsgBox "Por favor, informe um nome de usuário!", vbExclamation, "Login Inválido"
    cbxLogin.SetFocus
  ElseIf IsNull(txtSenha) Then
    MsgBox "Por favor, informe a senha!", vbExclamation, "Senha Inválida"
    txtSenha.SetFocus
  Else
    
    'Realizando a limpeza da senha
    strSenha = limparSenha(txtSenha)
  
    If verificaLogin(cbxLogin, strSenha) Then
      DoCmd.Close
      DoCmd.OpenForm "FPrincipal"
    Else
      MsgBox "Senha incorreta! Por favor, tente novamente.", vbExclamation, "Login"
      txtSenha.SetFocus
    End If
    
  End If
  
End Sub

Faça o teste novamente e veja o novo resultado. Agora o atacante não consegue mais acesso ao sistema. Contudo, não pense que estará livre de ataques apenas utilizando esta função. O universo das técnicas maliciosas é praticamente infinito. Lembre-se que este é apenas um exemplo.

Para saber mais sobre prevenção contra SQL Injection consulte os artigos abaixo:

http://pt.wikipedia.org/wiki/Inje%C3%A7%C3%A3o_de_SQL

http://www.mamura.com.br/como-se-prevenir-de-um-ataque-de-sql-injection/

http://www.macoratti.net/sql_inj.htm



PROCEDIMENTOS DE SEGURANÇA: ARMAZENAMENTO SEGURO

Até o momento nosso sistema já conta com um nível razoável de segurança, com verificação de senha forte e prevenção contra ataques de SQL Injection. Contudo, o que aconteceria se o atacante, de alguma maneira, conseguisse burlar o sistema e obter acesso não autorizado ao banco de dados?

Em primeiro lugar os dados dos usuários, assim como todos os outros dados, estariam expostos ao invasor. Você poderia pensar que não haveria maior problema nisso, pois já que o invasor está dentro do sistema, o que mais poderia piorar, não é mesmo?

Mas lembre-se que as senhas dos usuários estão armazenadas de maneira clara no banco de dados. Para este sistema, que já foi invadido, realmente isto não faz a menor diferença. Mas imagine se os usuários utilizarem as mesmas senhas em outros sistemas dentro da empresa, que ainda não foram invadidos. Pior que isso, pode ser que os usuários usem a mesma senha em suas contas de e-mail, redes sociais e sites de comércio eletrônico.

Outra hipótese é que um administrador de sistema mal intencionado poderia utilizar seu acesso ao banco de dados para roubar senhas dos usuários e usá-las em operações ilegais, nos outros sistemas onde o usuário possui conta, como por exemplo, os sites de compras pela internet. Não é porque uma pessoa administra um aplicativo que ela é totalmente honesta. O ideal, em qualquer sistema que exija login e senha, é que ninguém conheças as senhas dos usuários, a não ser eles próprios.

Você conseguiu visualizar quão sério é o problema?

Mas não se apavore. Há tempos existe uma solução para este caso. Basta armazenarmos, ao invés da senha às claras, um código secreto correspondente. Esta é a mesma técnica utilizada em assinatura digitail, na qual um software baseado em um algoritmo de cálculo de hash gera um código único na saída para cada sequência de texto distinta que for colocada na entrada.

Um dos algoritmos mais conhecidos capaz de realizar esta tarefa é o MD5. Ele recebe um texto qualquer como parâmetro e devolve um código hexadecimal de 32 caracteres. Este é o motivo de havermos criado, no início, o campo senha da tabela Usuario com o tamanho de 32 caracteres de texto. Segundo os pesquisadores, é praticamente impossível gerar o mesmo código a partir de duas entradas diferentes. Também é computacionalmente impraticável descobrir qual é o texto original a partir de um dado código de hash MD5.

Por este motivo, uma das técnicas mais seguras para armazenarmos senhas é gerar um hash MD5 e gravá-lo no banco de dados. Então, quando o usuário fizer o login no sistema refazemos o cálculo e comparamos o resultado, e não a senha original, com o código armazenado. Assim a senha permanece secreta e o único a conhecê-la continua sendo o usuário.

Claro que o sigilo da senha não depende somente desta técnica, pois quem tem acesso ao código fonte de um sistema facilmente obtem os dados do usuário. Para que tudo ocorra conforme planejado todas as outras regras de segurança devem ser implementadas.

Vamos, então, implementar o MD5 em nosso sistema. Em primeiro lugar baixe a classe de hash MD5 no endereço abaixo:

http://www.mabesi.com/downloads/viewdownload/10-access/52-classe-vba-hash-md5.html

Em seguida descompacte-a e importe para o seu sistema através do editor do VBA. Você pode encontrar a opção de importar arquivos em Arquivo -> Importar Arquivo, ou com o atalho de teclas Ctrl+M. Salve o seu projeto. Após importar a classe poderemos instanciar um objeto para utilizar os seus métodos.

Concluída esta parte, crie uma nova função no módulo FuncoesSeguranca, chamada getMD5(), conforme a seguir:

Function getMD5(argSenha As String) As String

  'Declarando um objeto da
  'classe HashMD5
  Dim objMD5 As New HashMD5
  
  'Utilizando o método DigestStrToHexStr para
  'obter um hash MD5 de 32 caracteres hexadecimais
  'a partir da senha informada.
  getMD5 = objMD5.DigestStrToHexStr(argSenha)

End Function

A geração do código MD5 poderia ser feita utilizando-se a biblioteca .NET presente no sistema, através da referência ao arquivo mscorlib.dll. Contudo, prefiro disponibilizar a classe contendo o código fonte, caso o leitor queira se aprofundar ainda mais, estudando-o.

Bem, ainda falta modificarmos o nosso código fonte para começar a salvar as senhas codificadas e também realizar a verificação de login utilizando a técnica de hash MD5. Como havíamos separado as funções responsáveis por estes procedimentos no início, ficará fácil ajustarmos o código.

Primeiro altere o procedimento alterarSenha(), no módulo ControleAcesso, da seguinte maneira:

Sub alterarSenha(argLogin As String, argSenha As String)

    Dim strSql As String
    
    'Convertendo a senha clara
    'em código hash MD5
    argSenha = getMD5(argSenha)

    strSql = "Update Usuario Set senha='" & argSenha & "'" & _
            "Where login='" & argLogin & "'"
    DoCmd.SetWarnings False
    DoCmd.RunSQL strSql
    DoCmd.SetWarnings True
    
End Sub

Com isso as senhas já estarão sendo armazenadas de maneira codificada. Agora precisamos alterar a função verificaLogin() para realizar a comparação de maneira também codificada. Faça os ajustes, conforme a seguir:

Function verificaLogin(argLogin As String, argSenha As String) As Boolean

    Dim criterio As String
    
    'Convertendo a senha clara
    'em código hash MD5 para
    'comparação e validação
    argSenha = getMD5(argSenha)
    
    criterio = "login='" & argLogin & "' And senha='" & argSenha & "'"
    
    If Nz(DCount("login", "Usuario", criterio), 0) > 0 Then
        verificaLogin = True
        setUsuarioAtual argLogin
    Else
        verificaLogin = False
    End If

End Function

Finalmente nosso pequeno projeto está pronto e funcional, incluindo as técnicas básicas de segurança. Mas antes de realizar o teste final você deve abrir o formulário FCadastroUsuario e redefinir as senhas de todos os usuários criados para a senha padrão. Isto é necessário, pois as senhas que ainda estão gravadas não estão codificadas. Como a comparação será realizada utilizando-se o hash MD5 as senhas não serão validadas antes de serem redefinidas.

Após realizar algumas alterações de senhas abra a tabela Usuario e veja como estão armazenadas as senhas agora. Íncrivel, não?

ENCERRAMENTO E AGRADECIMENTOS

Bem, chegamos ao fim de mais uma jornada de programação e aprendizado. Espero que o leitor tenha gostado da série de artigos e que os ensinamentos tenham sido úteis em seus projetos.

Reitero que as orientações aqui passadas são apenas noções de como construir um sistema seguro, no que diz respeito à identificação e validação de contas de usuário. Para dominar as técnicas é imprescindível continuar seus estudos e pesquisar cada assundo, aqui tratado, com mais profundidade.

Agradeço por ter acompanhado a série, assim como ficarei muito feliz caso receba comentários, sejam eles elogios ou críticas com sugestões de melhoria.

Felicidades e até o próximo trabalho.

Ah, e continue visitando o site. Ele foi feito para você!!!

Veja mais artigos na categoria Access.

Seja social. Compartilhe!