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
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.
No menu Project, clique em Add New Item.
Selecione o modelo Login Form e clique em Add.
O nome padrão do formulário de login é LoginForm1.
No menu Project, clique em Add New Item.
Selecione o modelo da Class, altere o nome para SampleIIdentity, e clique em Add.
No menu Project, clique em Add New Item.
Selecione o modelo da Class, altere o nome para SampleIPrincipal, e clique em Add.
No menu Project,clique em < ApplicationName> Properties .
No Project Designer, clique na guia Application.
Altere a lista Authentication mode para Application-defined.
Para configurar o formulário principal
Alternar para Form1 no Forms Designer.
Adicione um Button a Form1 a partir da Toolbox.
O nome padrão do botão é Button1.
Alterar o texto do botão para Authenticate.
Da Toolbox, adicione um Label a Form1.
O nome padrão do marcador é Label1.
Altere o texto do label para uma sequência vazia.
Do Toolbox,. Adicione um Label no Form1.
O nome padrão do marcador é Label2.
Altere o texto do label para uma sequência vazia.
Clique duas vezes em Button1 para criar o manipulador de eventos para o evento Click e em seguida, abra o Editor de Códigos.
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
Selecione o arquivo SampleIIdentity.vb no Solution Explorer.
Essa classe encapsula a identidade de um usuário.
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.
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
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 é " Custom Authentication ".Se os dados de autenticação de usuário foram armazenados em um banco de dados do SQL Server, o valor pode ser " SqlDatabase ".
Return "Custom Authentication"
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.
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
Criar uma propriedade que retorna a regra do usuário.
Public ReadOnly Property Role() As ApplicationServices.BuiltInRole Get Return roleValue End Get End Property
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
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
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 " Testando o aplicativo ".
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
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.
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.
Adicionar um campo privado para armazenar a identidade associada a este objeto.
Private identityValue As SampleIIdentity
Insira o código a seguir na propriedade Identity.
Return identityValue
A propriedade Identity precisa retornar a identidade do usuário do objeto atual.
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
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
Marque LoginForm1 no designer.
Clique duas vezes no botão OK para abrir o Editor de Código para o evento Click.
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
Inicie o aplicativo.
Clique em Authenticate.
O formulário logon abre.
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.
Clique OK para descartar a caixa de mensagem.
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.
Clique em Authenticate.
O formulário logon abre.
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
Referência
Outros recursos
Autenticação e Autorização no .NET Framework com o Visual Basic