Como: usar um validador personalizado de nome de usuário e senha
Por padrão, quando um nome de usuário e uma senha são usados para autenticação, o WCF (Windows Communication Foundation) usa o Windows para validar esses dados. No entanto, o WCF permite esquemas personalizados de autenticação de nome de usuário e senha, também conhecido como validadores. Para inserir um validador personalizado de nome de usuário e senha, crie uma classe que deriva de UserNamePasswordValidator e configure-a.
Para obter um aplicativo de exemplo, consulte o Validador de Nome de Usuário e Senha.
Para criar um validador personalizado de nome de usuário e senha
Crie uma classe que deriva de UserNamePasswordValidator.
public class CustomUserNameValidator : UserNamePasswordValidator {
Public Class CustomUserNameValidator Inherits UserNamePasswordValidator
Implemente o esquema de autenticação personalizado substituindo o método Validate.
Não use o código no exemplo a seguir que substitui o método Validate em um ambiente de produção. Substitua o código pelo esquema personalizado de validação de nome de usuário e senha, o que pode envolver recuperar pares de nome de usuário e senha de um banco de dados.
Para retornar erros de autenticação de volta para o cliente, gere um FaultException no método Validate.
// This method validates users. It allows in two users, test1 and test2 // with passwords 1tset and 2tset respectively. // This code is for illustration purposes only and // must not be used in a production environment because it is not secure. public override void Validate(string userName, string password) { if (null == userName || null == password) { throw new ArgumentNullException(); } if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset")) { // This throws an informative fault to the client. throw new FaultException("Unknown Username or Incorrect Password"); // When you do not want to throw an informative fault to the client, // throw the following exception. // throw new SecurityTokenException("Unknown Username or Incorrect Password"); } }
' This method validates users. It allows in two users, test1 and test2 ' with passwords 1tset and 2tset respectively. ' This code is for illustration purposes only and ' must not be used in a production environment because it is not secure. Public Overrides Sub Validate(ByVal userName As String, ByVal password As String) If Nothing = userName OrElse Nothing = password Then Throw New ArgumentNullException() End If If Not (userName = "test1" AndAlso password = "[PLACEHOLDER]") AndAlso Not (userName = "test2" AndAlso password = "[PLACEHOLDER]") Then ' This throws an informative fault to the client. Throw New FaultException("Unknown Username or Incorrect Password") ' When you do not want to throw an informative fault to the client, ' throw the following exception: ' Throw New SecurityTokenException("Unknown Username or Incorrect Password") End If End Sub
Para configurar um serviço para usar um validador personalizado de nome de usuário e senha
Configure uma associação que usa segurança de mensagem sobre qualquer transporte ou segurança em nível de transporte sobre HTTP.
Ao usar a segurança de mensagem, adicione uma das associações fornecidas pelo sistema, como uma <wsHttpBinding> ou uma <customBinding> que dá suporte à segurança de mensagem e o tipo de credencial
UserName
.Ao usar a segurança em nível de transporte sobre HTTP(S), adicione o <wsHttpBinding> ou <basicHttpBinding>, um <netTcpBinding> ou um <customBinding> que use HTTP(S) e o esquema de autenticação
Basic
.Observação
Ao usar o .NET Framework 3.5 ou versões posteriores, você pode usar um validador personalizado de nome de usuário e senha com a segurança de mensagem e transporte. Com o WinFX, um validador personalizado de nome de usuário e senha só pode ser usado com segurança de mensagem.
Dica
Para obter mais informações sobre como usar <netTcpBinding> neste contexto, consulte <Segurança>.
No arquivo de configuração, no elemento <system.serviceModel>, adicione um elemento <bindings>.
Adicione um elemento <wsHttpBinding> ou <basicHttpBinding> à seção bindings. Para obter mais informações sobre como criar um elemento de associação WCF, consulte Como especificar uma associação de serviço na configuração.
Defina o atributo
mode
de <security> ou <security> comoMessage
,Transport
ouTransportWithMessageCredential
.Defina o atributo
clientCredentialType
de <message> ou <transport>.Ao usar a segurança de mensagem, defina o atributo
clientCredentialType
de <message> comoUserName
.Ao usar a segurança em nível de transporte sobre HTTP(S), defina o atributo
clientCredentialType
de <transport> ou <transport> comoBasic
.Observação
Quando um serviço do WCF está hospedado nos Serviços de Informações da Internet (IIS) usando a segurança em nível de transporte e a propriedade UserNamePasswordValidationMode está definida como Custom, o esquema de autenticação personalizada usa um subconjunto de autenticação do Windows. Isso ocorre porque, neste cenário, o IIS efetua a autenticação do Windows antes de o WCF chamar o autenticador personalizado.
Para obter mais informações sobre como criar um elemento de associação WCF, consulte Como especificar uma associação de serviço na configuração.
O exemplo a seguir mostra o código de configuração para a associação:
<system.serviceModel> <bindings> <wsHttpBinding> <binding name="Binding1"> <security mode="Message"> <message clientCredentialType="UserName" /> </security> </binding> </wsHttpBinding> </bindings> </system.serviceModel>
Configure um comportamento que especifica que um validador personalizado de nome de usuário e senha é usado para validar os pares de nome de usuário e senha para tokens de segurança de entrada do UserNameSecurityToken.
Como um filho do elemento <system.serviceModel>, adicione um elemento <behaviours>.
Adicione um <serviceBehaviors> ao elemento <behaviors>.
Adicione um elemento <behavior> e defina o atributo
name
com um valor apropriado.Adicione um <serviceCredentials> ao elemento <behavior>.
Adicione um <userNameAuthentication> ao <serviceCredentials>.
Defina o
userNamePasswordValidationMode
paraCustom
.Importante
Se o valor de
userNamePasswordValidationMode
não estiver definido, o WCF usará a autenticação do Windows em vez do validador personalizado de nome de usuário e senha.Defina
customUserNamePasswordValidatorType
como o tipo que representa o seu validador personalizado de nome de usuário e senha.
O exemplo a seguir mostra o fragmento do
<serviceCredentials>
até este ponto:<serviceCredentials> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService.CustomUserNameValidator, service" /> </serviceCredentials>
Exemplo
O exemplo de código a seguir demonstra como criar um validador personalizado de nome de usuário e senha. Não use o código que substitui o método Validate em um ambiente de produção. Substitua o código pelo esquema personalizado de validação de nome de usuário e senha, o que pode envolver recuperar pares de nome de usuário e senha de um banco de dados.
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Principal;
using System.ServiceModel;
Imports System.IdentityModel.Selectors
Imports System.IdentityModel.Tokens
Imports System.Security.Principal
Imports System.ServiceModel
public class CustomUserNameValidator : UserNamePasswordValidator
{
// This method validates users. It allows in two users, test1 and test2
// with passwords 1tset and 2tset respectively.
// This code is for illustration purposes only and
// must not be used in a production environment because it is not secure.
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
{
// This throws an informative fault to the client.
throw new FaultException("Unknown Username or Incorrect Password");
// When you do not want to throw an informative fault to the client,
// throw the following exception.
// throw new SecurityTokenException("Unknown Username or Incorrect Password");
}
}
}
Public Class CustomUserNameValidator
Inherits UserNamePasswordValidator
' This method validates users. It allows in two users, test1 and test2
' with passwords 1tset and 2tset respectively.
' This code is for illustration purposes only and
' must not be used in a production environment because it is not secure.
Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
If Nothing = userName OrElse Nothing = password Then
Throw New ArgumentNullException()
End If
If Not (userName = "test1" AndAlso password = "[PLACEHOLDER]") AndAlso Not (userName = "test2" AndAlso password = "[PLACEHOLDER]") Then
' This throws an informative fault to the client.
Throw New FaultException("Unknown Username or Incorrect Password")
' When you do not want to throw an informative fault to the client,
' throw the following exception:
' Throw New SecurityTokenException("Unknown Username or Incorrect Password")
End If
End Sub
End Class