Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este ejemplo se muestra cómo implementar un autenticador de tokens personalizado. Un autenticador de tokens en Windows Communication Foundation (WCF) se usa para validar el token que se usa con el mensaje, comprobar que es auto coherente y autenticar la identidad asociada al token.
Los autenticadores de tokens personalizados son útiles en una variedad de casos, como:
Si desea invalidar el mecanismo de autenticación predeterminado asociado a un token.
Al crear un token personalizado.
En este ejemplo se muestra lo siguiente:
Cómo se puede autenticar un cliente mediante un par de nombre de usuario y contraseña.
Cómo el servidor puede validar las credenciales de cliente mediante un autenticador de tokens personalizado.
Cómo se vincula el código del servicio WCF con el autenticador de tokens personalizado.
Cómo se puede autenticar el servidor mediante el certificado X.509 del servidor.
En este ejemplo también se muestra cómo se puede acceder a la identidad del autor de la llamada desde WCF después del proceso de autenticación de token personalizado.
El servicio expone un único punto de conexión para comunicarse con el servicio, definido mediante el archivo de configuración de App.config. El punto de conexión está compuesto por una dirección, un enlace y un contrato. El enlace se configura con un wsHttpBindingestándar, con el conjunto de modo de seguridad en mensaje - el modo predeterminado de wsHttpBinding. En este ejemplo se establece el estándar wsHttpBinding para usar la autenticación de nombre de usuario de cliente. El servicio también configura el certificado de servicio mediante el comportamiento serviceCredentials. El securityCredentials comportamiento permite especificar un certificado de servicio. Un cliente usa un certificado de servicio para autenticar el servicio y proporcionar protección de mensajes. La siguiente configuración hace referencia al certificado localhost instalado durante la configuración de ejemplo, tal como se describe en las instrucciones de instalación siguientes.
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<!-- configure base address provided by host -->
<add baseAddress ="http://localhost:8000/servicemodelsamples/service" />
</baseAddresses>
</host>
<!-- use base address provided by host -->
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by a client to authenticate the service and provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
.... -->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
La configuración del punto de conexión de cliente consta de un nombre de configuración, una dirección absoluta para el punto de conexión de servicio, el enlace y el contrato. El enlace de cliente se configura con los valores adecuados Mode y clientCredentialType.
<system.serviceModel>
<client>
<endpoint name=""
address="http://localhost:8000/servicemodelsamples/service"
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
La implementación del cliente establece el nombre de usuario y la contraseña que se van a usar.
static void Main()
{
...
client.ClientCredentials.UserNamePassword.UserName = username;
client.ClientCredentials.UserNamePassword.Password = password;
...
}
Autenticador de token personalizado
Siga estos pasos para crear un autenticador de tokens personalizado:
Escriba un autenticador de token personalizado.
El ejemplo implementa un autenticador de tokens personalizado que valida que el nombre de usuario tiene un formato de correo electrónico válido. Deriva UserNameSecurityTokenAuthenticator. El método más importante de esta clase es ValidateUserNamePasswordCore(String, String). En este método, el autenticador valida el formato del nombre de usuario y también que el nombre de host no procede de un dominio no autorizado. Si se cumplen ambas condiciones, a continuación, devuelve una colección de solo lectura de instancias IAuthorizationPolicy que se utiliza a continuación para proporcionar indicaciones que representan la información almacenada dentro del token del nombre de usuario.
protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateUserNamePasswordCore(string userName, string password) { if (!ValidateUserNameFormat(userName)) throw new SecurityTokenValidationException("Incorrect UserName format"); ClaimSet claimSet = new DefaultClaimSet(ClaimSet.System, new Claim(ClaimTypes.Name, userName, Rights.PossessProperty)); List<IIdentity> identities = new List<IIdentity>(1); identities.Add(new GenericIdentity(userName)); List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1); policies.Add(new UnconditionalPolicy(ClaimSet.System, claimSet, DateTime.MaxValue.ToUniversalTime(), identities)); return policies.AsReadOnly(); }Proporcione una directiva de autorización devuelta por el autenticador de tokens personalizado.
Este ejemplo proporciona su propia implementación de IAuthorizationPolicy llamada
UnconditionalPolicyque devuelve un conjunto de indicaciones e identidades que se pasaron a él en su constructor.class UnconditionalPolicy : IAuthorizationPolicy { String id = Guid.NewGuid().ToString(); ClaimSet issuer; ClaimSet issuance; DateTime expirationTime; IList<IIdentity> identities; public UnconditionalPolicy(ClaimSet issuer, ClaimSet issuance, DateTime expirationTime, IList<IIdentity> identities) { if (issuer == null) throw new ArgumentNullException("issuer"); if (issuance == null) throw new ArgumentNullException("issuance"); this.issuer = issuer; this.issuance = issuance; this.identities = identities; this.expirationTime = expirationTime; } public string Id { get { return this.id; } } public ClaimSet Issuer { get { return this.issuer; } } public DateTime ExpirationTime { get { return this.expirationTime; } } public bool Evaluate(EvaluationContext evaluationContext, ref object state) { evaluationContext.AddToTarget(this, this.issuance); if (this.identities != null) { object value; IList<IIdentity> contextIdentities; if (!evaluationContext.Properties.TryGetValue("Identities", out value)) { contextIdentities = new List<IIdentity>(this.identities.Count); evaluationContext.Properties.Add("Identities", contextIdentities); } else { contextIdentities = value as IList<IIdentity>; } foreach (IIdentity identity in this.identities) { contextIdentities.Add(identity); } } evaluationContext.RecordExpirationTime(this.expirationTime); return true; } }Escriba un administrador de tokens de seguridad personalizado.
SecurityTokenManager se utiliza para crear un SecurityTokenAuthenticator para objetos SecurityTokenRequirement específicos que se le pasan en el método
CreateSecurityTokenAuthenticator. El administrador de tokens de seguridad también se usa para crear proveedores de tokens y serializadores de tokens, pero estos no están cubiertos por este ejemplo. En este ejemplo, el administrador de tokens de seguridad personalizado hereda de la clase ServiceCredentialsSecurityTokenManager e invalida el métodoCreateSecurityTokenAuthenticatorpara devolver el autenticador de tokens de nombre de usuario personalizado cuando los requisitos de token pasados indican que se solicita el autenticador de nombre de usuario.public class MySecurityTokenManager : ServiceCredentialsSecurityTokenManager { MyUserNameCredential myUserNameCredential; public MySecurityTokenManager(MyUserNameCredential myUserNameCredential) : base(myUserNameCredential) { this.myUserNameCredential = myUserNameCredential; } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { if (tokenRequirement.TokenType == SecurityTokenTypes.UserName) { outOfBandTokenResolver = null; return new MyTokenAuthenticator(); } else { return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } } }Escriba una credencial de servicio personalizada.
La clase de credenciales de servicio se usa para representar las credenciales configuradas para el servicio y crea un administrador de tokens de seguridad que se usa para obtener autenticadores de tokens, proveedores de tokens y serializadores de tokens.
public class MyUserNameCredential : ServiceCredentials { public MyUserNameCredential() : base() { } protected override ServiceCredentials CloneCore() { return new MyUserNameCredential(); } public override SecurityTokenManager CreateSecurityTokenManager() { return new MySecurityTokenManager(this); } }Configure el servicio para usar la credencial de servicio personalizada.
Para que el servicio use la credencial de servicio personalizada, eliminamos la clase de credenciales de servicio predeterminada después de capturar el certificado de servicio que ya está preconfigurado en la credencial de servicio predeterminada y configuramos la nueva instancia de credenciales de servicio para usar los certificados de servicio preconfigurados y agregamos esta nueva instancia de credenciales de servicio a comportamientos de servicio.
ServiceCredentials sc = serviceHost.Credentials; X509Certificate2 cert = sc.ServiceCertificate.Certificate; MyUserNameCredential serviceCredential = new MyUserNameCredential(); serviceCredential.ServiceCertificate.Certificate = cert; serviceHost.Description.Behaviors.Remove((typeof(ServiceCredentials))); serviceHost.Description.Behaviors.Add(serviceCredential);
Para mostrar la información del llamante, puede usar PrimaryIdentity como se muestra en el código siguiente. Current contiene información de las notificaciones sobre el llamador actual.
static void DisplayIdentityInformation()
{
Console.WriteLine("\t\tSecurity context identity : {0}",
ServiceSecurityContext.Current.PrimaryIdentity.Name);
return;
}
Al ejecutar el ejemplo, las solicitudes de operación y las respuestas se muestran en la ventana de la consola del cliente. Presione ENTRAR en la ventana del cliente para apagar el cliente.
Instalar el archivo por lotes
El Setup.bat archivo por lotes incluido con este ejemplo permite configurar el servidor con certificados pertinentes para ejecutar una aplicación autohospedada que requiera seguridad basada en certificados de servidor. Este archivo por lotes debe modificarse para que funcione en varios equipos o en un escenario sin hospedaje.
A continuación se proporciona una breve introducción a las distintas secciones de los archivos por lotes para que se puedan modificar para que se ejecuten en la configuración adecuada.
Creación del certificado de servidor.
Las líneas siguientes del archivo por lotes de Setup.bat crean el certificado de servidor que se va a usar. La variable
%SERVER_NAME%especifica el nombre del servidor. Cambie esta variable para especificar su propio nombre de servidor. El valor predeterminado en este archivo por lotes es el host local.echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -peInstalar el certificado de servidor en el almacén de certificados de confianza del cliente.
Las líneas siguientes del archivo por lotes Setup.bat copian el certificado de servidor en el almacén de los usuarios de confianza del cliente. Este paso es necesario porque el sistema cliente no confía implícitamente en los certificados generados por Makecert.exe. Si ya tiene un certificado que se basa en un certificado raíz de confianza de cliente (por ejemplo, un certificado emitido por Microsoft), este paso para rellenar el almacén de certificados de cliente con el certificado de servidor no es necesario.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeopleNota:
El archivo por lotes de instalación está diseñado para ejecutarse desde un terminal del SDK de Windows. Requiere que la variable de entorno de MSSDK se dirija al directorio donde está instalado el SDK. Esta variable de entorno se establece automáticamente dentro de un símbolo del sistema de Windows SDK.
Para instalar y compilar el ejemplo
Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.
Para compilar la solución, siga las instrucciones que se indican en Compilación de los ejemplos de Windows Communication Foundation.
Para ejecutar el ejemplo en el mismo equipo
Ejecute el comando Setup.bat en la carpeta de instalación de ejemplo dentro de una ventana de comandos de Visual Studio abierta con privilegios de administrador. Esto instala todos los certificados necesarios para ejecutar el ejemplo.
Nota:
El archivo por lotes Setup.bat está diseñado para ejecutarse desde el símbolo del sistema de Visual Studio. La variable de entorno PATH que se establece en el símbolo del sistema de Visual Studio señala al directorio que contiene los archivos ejecutables que requiere el script Setup.bat.
Inicie service.exe desde service\bin.
Inicie client.exe desde \client\bin. La actividad de cliente se muestra en la aplicación de consola cliente.
Si el cliente y el servicio no pueden comunicarse, consulte Sugerencias de solución de problemas para ejemplos de WCF.
Para ejecutar el ejemplo entre equipos
Cree un directorio en el equipo de servicio para los archivos binarios del servicio.
Copie los archivos del programa de servicio en el directorio del servicio en el equipo destinado al servicio. Copie también los archivos Setup.bat y Cleanup.bat en el equipo de servicio.
Debe tener un certificado de servidor con el nombre del sujeto que contiene el nombre de dominio completo del equipo. El servicio App.config archivo debe actualizarse para reflejar este nuevo nombre de certificado. Puede crear uno utilizando el Setup.bat si establece la variable
%SERVER_NAME%en el nombre de host totalmente cualificado del equipo en el que se ejecutará el servicio. Tenga en cuenta que el archivo setup.bat debe ejecutarse desde el Símbolo del sistema para desarrolladores de Visual Studio con privilegios de administrador.Copie el certificado de servidor en el almacén CurrentUser-TrustedPeople del cliente. No es necesario hacerlo, excepto cuando el certificado de servidor es emitido por un emisor de confianza del cliente.
En el archivo App.config del ordenador de servicio, cambie el valor de la dirección base para especificar un nombre de equipo totalmente calificado en lugar de localhost.
En el equipo del servicio, ejecute service.exe desde un símbolo del sistema.
Copie los archivos de programa cliente de la carpeta \client\bin\, en la carpeta específica del idioma, en el equipo cliente.
En el archivo Client.exe.config del equipo cliente, cambie el valor de dirección del punto de conexión para que coincida con la nueva dirección del servicio.
En el equipo cliente, inicie Client.exe desde un símbolo del sistema.
Si el cliente y el servicio no pueden comunicarse, consulte Sugerencias de solución de problemas para ejemplos de WCF.
Para limpiar después de la muestra.
- Ejecute Cleanup.bat en la carpeta samples una vez que haya terminado de ejecutar el ejemplo.