Demonstra Passo a passo: Implementando autenticação personalizada e autorização

Essa explicação passo a passo demonstra como implementar autenticação e autorização personalizadas usando classes que derivam de IIdentity e IPrincipal.Essa explicação passo a passo demonstra também como substituir a identidade padrão da thread do aplicativo, a identidade do Windows, definindo My.User.CurrentPrincipal como uma instância da classe que é derivada de IPrincipal.As informações do novo usuário estão disponíveis imediatamente pelo objeto My.User,que retorna informações sobre identidade do usuário atual da thread.

Aplicativos comerciais geralmente fornecem acesso a dados ou recursos com base no credenciais fornecidas pelo usuário.Normalmente, esses aplicativos verificam a função de um usuário e fornecem acesso a recursos com base nessa função.O Common Language Runtime fornece o suporte para autorização baseada em função baseado em uma conta do Windows ou uma identidade personalizada.Para obter mais informações, consulte Segurança baseada em função.

Guia de Introdução

Primeiro, configurar um projeto com um formulário principal e um formulário de logon, e configurá-lo para usar autenticação personalizada.

Para criar o aplicativo de exemplo

  1. Criar um novo projeto de aplicativo do Windows do Visual Basic.Para obter mais informações, consulte Como: Criar um projeto de aplicativo do Windows.

    O nome padrão do formulário principal é Form1.

  2. No menu Project, clique em Add New Item.

  3. Selecione o modelo Login Form e clique em Add.

    O nome padrão do formulário de login é LoginForm1.

  4. No menu Project, clique em Add New Item.

  5. Selecione o modelo da Class, altere o nome para SampleIIdentity, e clique em Add.

  6. No menu Project, clique em Add New Item.

  7. Selecione o modelo da Class, altere o nome para SampleIPrincipal, e clique em Add.

  8. No menu Project,clique em < ApplicationName> Properties .

  9. No Project Designer, clique na guia Application.

  10. Altere a lista Authentication mode para Application-defined.

Para configurar o formulário principal

  1. Alternar para Form1 no Forms Designer.

  2. Adicione um Button a Form1 a partir da Toolbox.

    O nome padrão do botão é Button1.

  3. Alterar o texto do botão para Authenticate.

  4. Da Toolbox, adicione um Label a Form1.

    O nome padrão do marcador é Label1.

  5. Altere o texto do label para uma sequência vazia.

  6. Do Toolbox,. Adicione um Label no Form1.

    O nome padrão do marcador é Label2.

  7. Altere o texto do label para uma sequência vazia.

  8. Clique duas vezes em Button1 para criar o manipulador de eventos para o evento Click e em seguida, abra o Editor de Códigos.

  9. Adicione o seguinte código ao método Button1_Click.

    My.Forms.LoginForm1.ShowDialog()
    ' Check if the user was authenticated.
    If My.User.IsAuthenticated Then
        Me.Label1.Text = "Authenticated " & My.User.Name
    Else
        Me.Label1.Text = "User not authenticated"
    End If
    
    If My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator) Then
        Me.Label2.Text = "User is an Administrator"
    Else
        Me.Label2.Text = "User is not an Administrator"
    End If
    

Você pode executar o aplicativo, mas porque não há nenhum código de autenticação, você não poderá autenticar qualquer usuário.Adicionando código de autenticação é discutido na seção a seguir.

Criar uma identidade

O .NET Framework usa o IIdentity e interfaces IPrincipal como a base para autenticação e autorização.O aplicativo pode usar a autenticação personalizada de usuário ao implementar essas interfaces, como demonstram esses procedimentos.

Para criar uma classe que implementa IIdentity

  1. Selecione o arquivo SampleIIdentity.vb no Solution Explorer.

    Essa classe encapsula a identidade de um usuário.

  2. Na linha seguinte a Public Class SampleIIdentity, adicione o seguinte código para herdar de IIdentity.

    Implements System.Security.Principal.IIdentity
    

    Após adicionar aquele código e pressionar ENTER, o Code Editor cria propriedades stub que você deve implementar.

  3. Adicionar campos privados para armazenar o nome de usuário e um valor que indica se o usuário é autenticado.

    Private nameValue As String
    Private authenticatedValue As Boolean
    Private roleValue As ApplicationServices.BuiltInRole
    
  4. Insira o código a seguir na propriedade AuthenticationType.

    A propriedade AuthenticationType precisa retornar uma sequência de caracteres que indica o mecanismo de autenticação atual.

    Este exemplo usa autenticação explicitamente especificada, portanto a sequência é &quot; Custom Authentication &quot;.Se os dados de autenticação de usuário foram armazenados em um banco de dados do SQL Server, o valor pode ser &quot; SqlDatabase &quot;.

    Return "Custom Authentication"
    
  5. Insira o código a seguir na propriedade IsAuthenticated.

    Return authenticatedValue
    

    A propriedade IsAuthenticated precisa retornar um valor que indica se o usuário foi autenticado.

  6. A propriedade Name precisa retornar o nome do usuário associado com essa identidade.

    Insira o código a seguir na propriedade Name.

    Return nameValue
    
  7. Criar uma propriedade que retorna a regra do usuário.

    Public ReadOnly Property Role() As ApplicationServices.BuiltInRole
        Get
            Return roleValue
        End Get
    End Property
    
  8. Crie um método Sub New que inicializa a classe autenticando o usuário e, em seguida, definindo o nome de usuário e regra com base em um nome e uma senha.

    Este método chama um método chamado IsValidNameAndPassword para determinar se uma combinação de nome de usuário e de senha é válida.

    Public Sub New(ByVal name As String, ByVal password As String)
        ' The name is not case sensitive, but the password is.
        If IsValidNameAndPassword(name, password) Then
            nameValue = name
            authenticatedValue = True
            roleValue = ApplicationServices.BuiltInRole.Administrator
        Else
            nameValue = ""
            authenticatedValue = False
            roleValue = ApplicationServices.BuiltInRole.Guest
        End If
    End Sub
    
  9. Crie um método chamado IsValidNameAndPassword que determina se uma combinação de nome de usuário e senha é válida.

    Observação de segurança:

    O algoritmo de autenticação deve tratar senhas com segurança.F ou exemplo, a senha não deve ser armazenada em um campo de classe.

    Você não deve armazenar senhas de usuário em seu sistema, porque se essa informação é vazada, não há mais nenhuma segurança.Você pode armazenar a hash de senha de cada usuário.(Uma função de hash embaralha os dados para a entrada de forma que não pode ser deduzida a partir da saída.) Uma senha não pode ser determinada diretamente do hash de uma senha.

    Entretanto, um usuário mal-intencionado pode gastar tempo para gerar um dicionário dos hashes de todas as senhas possíveis e então pesquisar a senha para um hash determinado.Para proteger contra esse tipo de ataque, você deve adicionar salt para a senha antes gerar o código hash, para gerar um salted hash.Salt é um dado extra que é único para cada senha que torna impossível pré-computar um dicionário hash.

    Para proteger as senhas de usuários mal-intencionados, você deve armazenar apenas Hashes salted das senhas, preferencialmente em um computador seguro.É muito difícil para um usuário mal-intencionado recuperar uma senha de um salted hash.Este exemplo usa os métodos GetHashedPassword e GetSalt para carregar a senha de hash e sal de um usuário.

    Private Function IsValidNameAndPassword( _
        ByVal username As String, _
        ByVal password As String) _
        As Boolean
    
        ' Look up the stored hashed password and salt for the username.
        Dim storedHashedPW As String = GetHashedPassword(username)
        Dim salt As String = GetSalt(username)
    
        'Create the salted hash.
        Dim rawSalted As String = salt & Trim(password)
        Dim saltedPwBytes() As Byte = _
            System.Text.Encoding.Unicode.GetBytes(rawSalted)
        Dim sha1 As New _
            System.Security.Cryptography.SHA1CryptoServiceProvider
        Dim hashedPwBytes() As Byte = sha1.ComputeHash(saltedPwBytes)
        Dim hashedPw As String = Convert.ToBase64String(hashedPwBytes)
    
        ' Compare the hashed password with the stored password.
        Return hashedPw = storedHashedPW
    End Function
    
  10. Criar funções chamadas GetHashedPassword e GetSalt que retornam a senha da hash e sal para o usuário especificado.

    Observação de segurança:

    Você deve evitar c de disco rígido oding as senhas hashed e salts em seus aplicativos de cliente por dois motivos.Primeiro, usuário mal-intencionado pode ser capaz de acessá-lo e localizar uma colisão de hash.Segundo, você não pode alterar ou revogar uma senha de usuário.O aplicativo deve obter o hash senha e salt para um determinado usuário de uma fonte segura que um administrador mantém.

    Embora, para maior facilidade, este exemplo tem um código rígido, senha hashed e salt, você deve usar uma abordagem mais segura no código de produção.Por exemplo, você pode armazenar as informações do usuário em um banco de dados do SQL Server e acessá-lo com stored procedures.Para obter mais informações, consulte Como: Conectar-se a Dados em um Banco de Dados.

    Observação:

    A senha correspondente a este código rígido de senha Hashed é fornecida na seção &quot; Testando o aplicativo &quot;.

    Private Function GetHashedPassword(ByVal username As String) As String
        ' Code that gets the user's hashed password goes here.
        ' This example uses a hard-coded hashed passcode.
        ' In general, the hashed passcode should be stored 
        ' outside of the application.
        If Trim(username).ToLower = "testuser" Then
            Return "ZFFzgfsGjgtmExzWBRmZI5S4w6o="
        Else
            Return ""
        End If
    End Function
    
    Private Function GetSalt(ByVal username As String) As String
        ' Code that gets the user's salt goes here.
        ' This example uses a hard-coded salt.
        ' In general, the salt should be stored 
        ' outside of the application.
        If Trim(username).ToLower = "testuser" Then
            Return "Should be a different random value for each user"
        Else
            Return ""
        End If
    End Function
    

Agora o arquivo SampleIIdentity.vb deve conter o código a seguir:

Public Class SampleIIdentity
    Implements System.Security.Principal.IIdentity

    Private nameValue As String
    Private authenticatedValue As Boolean
    Private roleValue As ApplicationServices.BuiltInRole

    Public ReadOnly Property AuthenticationType() As String Implements System.Security.Principal.IIdentity.AuthenticationType
        Get
            Return "Custom Authentication"
        End Get
    End Property

    Public ReadOnly Property IsAuthenticated() As Boolean Implements System.Security.Principal.IIdentity.IsAuthenticated
        Get
            Return authenticatedValue
        End Get
    End Property

    Public ReadOnly Property Name() As String Implements System.Security.Principal.IIdentity.Name
        Get
            Return nameValue
        End Get
    End Property

    Public ReadOnly Property Role() As ApplicationServices.BuiltInRole
        Get
            Return roleValue
        End Get
    End Property

    Public Sub New(ByVal name As String, ByVal password As String)
        ' The name is not case sensitive, but the password is.
        If IsValidNameAndPassword(name, password) Then
            nameValue = name
            authenticatedValue = True
            roleValue = ApplicationServices.BuiltInRole.Administrator
        Else
            nameValue = ""
            authenticatedValue = False
            roleValue = ApplicationServices.BuiltInRole.Guest
        End If
    End Sub

    Private Function IsValidNameAndPassword( _
        ByVal username As String, _
        ByVal password As String) _
        As Boolean

        ' Look up the stored hashed password and salt for the username.
        Dim storedHashedPW As String = GetHashedPassword(username)
        Dim salt As String = GetSalt(username)

        'Create the salted hash.
        Dim rawSalted As String = salt & Trim(password)
        Dim saltedPwBytes() As Byte = _
            System.Text.Encoding.Unicode.GetBytes(rawSalted)
        Dim sha1 As New _
            System.Security.Cryptography.SHA1CryptoServiceProvider
        Dim hashedPwBytes() As Byte = sha1.ComputeHash(saltedPwBytes)
        Dim hashedPw As String = Convert.ToBase64String(hashedPwBytes)

        ' Compare the hashed password with the stored password.
        Return hashedPw = storedHashedPW
    End Function

    Private Function GetHashedPassword(ByVal username As String) As String
        ' Code that gets the user's hashed password goes here.
        ' This example uses a hard-coded hashed passcode.
        ' In general, the hashed passcode should be stored 
        ' outside of the application.
        If Trim(username).ToLower = "testuser" Then
            Return "ZFFzgfsGjgtmExzWBRmZI5S4w6o="
        Else
            Return ""
        End If
    End Function

    Private Function GetSalt(ByVal username As String) As String
        ' Code that gets the user's salt goes here.
        ' This example uses a hard-coded salt.
        ' In general, the salt should be stored 
        ' outside of the application.
        If Trim(username).ToLower = "testuser" Then
            Return "Should be a different random value for each user"
        Else
            Return ""
        End If
    End Function

End Class

Criando um principal

Em seguida, você precisará implementar uma classe que é derivada de IPrincipal, e tem seu retorno como as instâncias da classe SampleIIdentity.

Para criar uma classe que implementa IPrincipal

  1. Selecione o arquivo SampleIPrincipal.vb na Solution Explorer.

    Essa classe encapsula a identidade de um usuário.Você pode utilizar o objeto My.User para anexar este principal para o thread atual e acessar a identidade do usuário.

  2. Na linha seguinte a Public Class SampleIPrincipal, adicione o seguinte código para herdar de IPrincipal.

    Implements System.Security.Principal.IPrincipal
    

    Após adicionar o código e pressionar ENTER, o Code Editor cria uma propriedade stub e método que você deve implementar.

  3. Adicionar um campo privado para armazenar a identidade associada a este objeto.

    Private identityValue As SampleIIdentity
    
  4. Insira o código a seguir na propriedade Identity.

    Return identityValue
    

    A propriedade Identity precisa retornar a identidade do usuário do objeto atual.

  5. Digite o seguinte código no método IsInRole.

    O método IsInRole determina se o objeto atual principal pertence à função especificada.

    Return role = identityValue.Role.ToString
    
  6. Criar um método Sub New que inicializa a classe com uma nova instância de SampleIIdentity fornecida um nome de usuário e a senha.

    Public Sub New(ByVal name As String, ByVal password As String)
        identityValue = New SampleIIdentity(name, password)
    End Sub
    

    Esse código define a identidade do usuário para a classe SampleIPrincipal.

Agora o arquivo SampleIPrincipal.vb deve conter o código a seguir:

Public Class SampleIPrincipal
    Implements System.Security.Principal.IPrincipal

    Private identityValue As SampleIIdentity

    Public ReadOnly Property Identity() As System.Security.Principal.IIdentity Implements System.Security.Principal.IPrincipal.Identity
        Get
            Return identityValue
        End Get
    End Property

    Public Function IsInRole(ByVal role As String) As Boolean Implements System.Security.Principal.IPrincipal.IsInRole
        Return role = identityValue.Role.ToString
    End Function

    Public Sub New(ByVal name As String, ByVal password As String)
        identityValue = New SampleIIdentity(name, password)
    End Sub

End Class

Conectando ao formulário de logon

O aplicativo pode usar o formulário de logon para coletar um nome de usuário e senha.Ele pode usar essas informações para inicializar uma instância da classe SampleIPrincipal e usar o objeto My.User para definir a identidade da thread atual a essa instância.

Para configurar o formulário de logon

  1. Marque LoginForm1 no designer.

  2. Clique duas vezes no botão OK para abrir o Editor de Código para o evento Click.

  3. Substitua o método OK_Click pelo seguinte código.

    Dim samplePrincipal As New SampleIPrincipal( _
        Me.UsernameTextBox.Text, Me.PasswordTextBox.Text)
    Me.PasswordTextBox.Text = ""
    If (Not samplePrincipal.Identity.IsAuthenticated) Then
        ' The user is still not validated.
        MsgBox("The username and password pair is incorrect")
    Else
        ' Update the current principal.
        My.User.CurrentPrincipal = samplePrincipal
        Me.Close()
    End If
    

Testando o aplicativo

Agora que o aplicativo tem código de autenticação, você pode executar o aplicativo e tentar autenticar um usuário.

Para testar o aplicativo

  1. Inicie o aplicativo.

  2. Clique em Authenticate.

    O formulário logon abre.

  3. Digite TestUser na caixa User name e BadPassword na caixa Password, e clique OK.

    Uma caixa de mensagem abre informando este par de nome de usuário e senha estão incorretos.

  4. Clique OK para descartar a caixa de mensagem.

  5. Clique Cancel para descartar o formulário de logon.

    Os labels no formulário principal agora estão no estado User not authenticated e User is not an Administrator.

  6. Clique em Authenticate.

    O formulário logon abre.

  7. Digite TestUser na caixa de texto User Name e Password na caixa de texto Password e clique OK.Certifique-se que a senha seja inserida com o uso de maiúscula corretamente.

    Os labels no formulário principal agora dizem Authenticated TestUser e User is an Administrator.

Consulte também

Tarefas

Como: Conectar-se a Dados em um Banco de Dados

Conceitos

Acessando Dados do Usuário

Referência

Objeto My.User

IIdentity

IPrincipal

Outros recursos

Autenticação e Autorização no .NET Framework com o Visual Basic