Procedimiento para usar un nombre de usuario personalizado y un validador de contraseñas
De forma predeterminada, cuando un nombre de usuario y una contraseña se utilizan para la autenticación, Windows Communication Foundation (WCF) usa Windows para validarlos. Sin embargo, WCF permite esquemas de autenticación de nombre de usuario y contraseña personalizados, también conocidos como validadores. Para incorporar un nombre de usuario personalizado y un validador de contraseña, cree una clase que derive de UserNamePasswordValidator y, a continuación, configúrela.
Para ver una aplicación de ejemplo, consulte Validador de contraseñas de nombre de usuario.
Para crear un nombre de usuario personalizado y un validador de contraseñas
Cree una clase que derive de UserNamePasswordValidator.
public class CustomUserNameValidator : UserNamePasswordValidator {
Public Class CustomUserNameValidator Inherits UserNamePasswordValidator
Implemente el esquema personalizado de autenticación invalidando el método Validate.
No utilice el código en el ejemplo siguiente que invalida el método Validate en un entorno de producción. Reemplace el código con su nombre de usuario personalizado y esquema de validación de contraseña, que podrían implicar la recuperación de los pares de nombre de usuario y contraseña de una base de datos.
Para devolver errores de autenticación al cliente, genere una FaultException en el 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 un servicio con el fin de utilizar un nombre de usuario personalizado y un validador de contraseñas
Configure un enlace que utilice la seguridad de mensaje sobre cualquier transporte o la seguridad del nivel de transporte sobre HTTP(S).
Si usa la seguridad del mensaje, agregue uno de los enlaces proporcionados por el sistema, como <wsHttpBinding> o <customBinding> que admite la seguridad del mensaje y el tipo de credencial
UserName
.Al usar la seguridad de nivel de transporte a través de HTTP(S), agregue el elemento <wsHttpBinding> o <basicHttpBinding>, un elemento <netTcpBinding> o un elemento <customBinding> que use HTTP(S) y el esquema de autenticación
Basic
.Nota
Si se usa .NET Framework 3.5 o una versión posterior, puede usar un validador de nombre de usuario y contraseña personalizado con la seguridad del mensaje y del transporte. Con WinFX, solo puede usarse un validador de nombre de usuario y contraseña con la seguridad del mensaje.
Sugerencia
Para más información sobre el uso de <netTcpBinding> en este contexto, consulte <security>.
En el archivo de configuración, en el elemento < system.serviceModel>, agregue un elemento <bindings>.
Agregue un elemento <wsHttpBinding> o <basicHttpBinding> a la sección de enlaces. Para más información sobre cómo crear un elemento de enlace de WCF, consulte Especificación de un enlace de servicio en la configuración.
Establezca el atributo
mode
del elemento <security> o del elemento <security> enMessage
,Transport
oTransportWithMessageCredential
.Establezca el atributo
clientCredentialType
del elemento <message> o <transport>.Si usa la seguridad del mensaje, establezca el atributo
clientCredentialType
del elemento <message> enUserName
.Si usa la seguridad de nivel de transporte a través de HTTP(S), establezca el atributo
clientCredentialType
del elemento <transport> o <transport> enBasic
.Nota
Cuando un servicio WCF se hospeda en Internet Information Services (IIS) mediante la seguridad de nivel de transporte, y se establece la propiedad UserNamePasswordValidationMode en Custom, el esquema de autenticación personalizado utiliza un subconjunto de autenticación de Windows. Esto se debe a que en este escenario, IIS realiza la autenticación de Windows antes de que WCF invoque al autenticador personalizado.
Para más información sobre cómo crear un elemento de enlace de WCF, consulte Especificación de un enlace de servicio en la configuración.
El siguiente ejemplo muestra el código de configuración del enlace:
<system.serviceModel> <bindings> <wsHttpBinding> <binding name="Binding1"> <security mode="Message"> <message clientCredentialType="UserName" /> </security> </binding> </wsHttpBinding> </bindings> </system.serviceModel>
Configure un comportamiento que especifique que un nombre de usuario personalizado y el validador de contraseñas se utilizan para validar los pares de nombre de usuario y para los tokens de seguridad UserNameSecurityToken entrantes.
Como elemento secundario del elemento <system.serviceModel>, agregue un elemento <behaviors>.
Agregue un elemento <serviceBehaviors> al elemento <behaviors>.
Agregue un elemento <behavior> y establezca el atributo
name
en un valor apropiado.Agregue un elemento <serviceCredentials> al elemento <behavior>.
Agregue un elemento <userNameAuthentication> al elemento <serviceCredentials>.
Establecer
userNamePasswordValidationMode
enCustom
.Importante
Si no se establece el valor
userNamePasswordValidationMode
, WCF usa la autenticación de Windows en lugar de validador de nombre de usuario y contraseña personalizados.Establezca
customUserNamePasswordValidatorType
en el tipo que representa su nombre de usuario personalizado y el validador de la contraseña.
El ejemplo siguiente muestra el fragmento
<serviceCredentials>
en este punto:<serviceCredentials> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService.CustomUserNameValidator, service" /> </serviceCredentials>
Ejemplo
El ejemplo de código siguiente muestra cómo crear un nombre de usuario personalizado y el validador de la contraseña. No utilice el código que invalida el método Validate en un entorno de producción. Reemplace el código con su nombre de usuario personalizado y esquema de validación de contraseña, que podrían implicar la recuperación de los pares de nombre de usuario y contraseña de una base de datos.
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