2010-11-09 10 views
8

Tengo un servicio WCF que requiere un token de seguridad emitido por un servicio WCF STS separado. Todo esto funciona muy bien. En mi solicitud, yo uso el servicio de este modo:¿Cómo fuerzo una actualización del token de seguridad para un servicio WCF?

MyServiceClient myService = new MyServiceClient(); 
myService.Open(); 
myService.DoStuff(); 

El Servicio STS se llama para obtener una ficha y la ficha se utiliza para llamar al método de servicio DoStuff.

Una vez que finaliza el protocolo de enlace inicial, el objeto myService tiene el token en caché y lo vuelve a utilizar hasta que caduque. Este es un buen comportamiento y todo, pero ¿cómo lo haría forzar para actualizar el token?

myService.ClientCredentials.Invalidate(); // something like this? 

De tal manera que si llamaba a DoStuff() de nuevo se sabría que tiene que ir a la STS de nuevo tanto como lo hizo la primera vez.

¿Estoy atascado simplemente haciendo un nuevo objeto de clase proxy, es decir, myService = new MyServiceClient();? Esto funciona pero parece ser la solución de la bomba nuclear.

Alternativamente, ¿hay alguna forma de obtener manualmente un nuevo token y reemplazar el actual, es decir, myService.ClientCredentials.Renew();?

Si tengo que hacer una clase ClientCredentials personalizada para hacer esto, ¿cómo implementaría los métodos de ejemplo anteriores?

Respuesta

4

En mi base de código, en realidad almacenamos en caché el token, por lo que nos aseguramos de no realizar llamadas repetidas al STS. Usando el mismo método, definitivamente puedes modificarlo manualmente para solicitar otro token cuando lo desees. Así es como enlazar en ClientCredentials:

public class CustomClientCredentials : ClientCredentials 
{ 
    public CustomClientCredentials() 
    { 
    } 

    protected CustomClientCredentials(ClientCredentials other) 
     : base(other) 
    { 
    } 

    protected override ClientCredentials CloneCore() 
    { 
     return new CustomClientCredentials(this); 
    } 

    /// <summary> 
    /// Returns a custom security token manager 
    /// </summary> 
    /// <returns></returns> 
    public override SecurityTokenManager CreateSecurityTokenManager() 
    { 
     return new CustomClientCredentialsSecurityTokenManager(this); 
    } 
} 


public class CustomClientCredentialsSecurityTokenManager : ClientCredentialsSecurityTokenManager 
{ 
    public CustomClientCredentialsSecurityTokenManager(ClientCredentials credentials) 
     : base(credentials) 
    { 
    } 

    /// <summary> 
    /// Returns a custom token provider when a issued token is required 
    /// </summary> 
    public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement) 
    { 
     if (IsIssuedSecurityTokenRequirement(tokenRequirement)) 
     { 
      // Adds the endpoint behaviors for calling the issuer 
      IssuedSecurityTokenProvider baseProvider = (IssuedSecurityTokenProvider)base.CreateSecurityTokenProvider(tokenRequirement); 

      CustomIssuedSecurityTokenProvider provider = new CustomIssuedSecurityTokenProvider(baseProvider); 
      return provider; 
     } 
     return base.CreateSecurityTokenProvider(tokenRequirement); 
    } 
} 


public class CustomIssuedSecurityTokenProvider : IssuedSecurityTokenProvider 
{ 
    private readonly IssuedSecurityTokenProvider _innerProvider; 

    public CustomIssuedSecurityTokenProvider(IssuedSecurityTokenProvider innerProvider) 
    { 
     _innerProvider = innerProvider; 
     CacheIssuedTokens = innerProvider.CacheIssuedTokens; 
     IdentityVerifier = innerProvider.IdentityVerifier; 
     IssuedTokenRenewalThresholdPercentage = innerProvider.IssuedTokenRenewalThresholdPercentage; 
     IssuerAddress = innerProvider.IssuerAddress; 
     IssuerBinding = innerProvider.IssuerBinding; 
     innerProvider.IssuerChannelBehaviors.ForEach(IssuerChannelBehaviors.Add); 
     KeyEntropyMode = innerProvider.KeyEntropyMode; 
     MaxIssuedTokenCachingTime = innerProvider.MaxIssuedTokenCachingTime; 
     MessageSecurityVersion = innerProvider.MessageSecurityVersion; 
     SecurityAlgorithmSuite = innerProvider.SecurityAlgorithmSuite; 
     SecurityTokenSerializer = innerProvider.SecurityTokenSerializer; 
     TargetAddress = innerProvider.TargetAddress; 
     innerProvider.TokenRequestParameters.ForEach(TokenRequestParameters.Add); 

     _innerProvider.Open(); 
    } 

    ~CustomIssuedSecurityTokenProvider() 
    { 
     _innerProvider.Close(); 
    } 

    protected override SecurityToken GetTokenCore(TimeSpan timeout) 
    { 
     // We're ignoring the CacheIssuedTokens property in order to force an STS call 
     var securityToken = _innerProvider.GetToken(timeout); 
     return securityToken; 
    } 
} 

El método GetTokenCore() es donde el STS es llamado. Cuando llame a GetToken(), se le pedirá al STS que emita otro token.

De su pregunta, supongo que sabe cómo conectar sus ClientCredentials desde app.config.

Puede haber una manera de establecer la propiedad CacheIssuedTokens en el archivo App.config, no estoy seguro de estar lejos de mi cabeza.

1

¿No podría usar la propiedad IssuedToken.MaxIssuedTokenCachingTime y establecerla en 0?

Cuestiones relacionadas