Как принудительно обновить токен безопасности для службы WCF?

У меня есть служба WCF, для которой требуется токен безопасности, выданный отдельной службой WCF STS. Это все работает просто денди. В моем приложении я использую сервис следующим образом:

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

Служба STS вызывается для получения маркера, а маркер используется для вызова метода службы DoStuff.

Однако после того, как начальное рукопожатие завершено, объект myService кэширует токен и повторно использует его до истечения срока его действия. Это нормальное поведение и все такое, но как мне заставить обновить токен?

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

Таким образом, если я снова вызову DoStuff(), он будет знать, что ему нужно снова обратиться к STS, как и в первый раз.

Я застрял, просто создавая новый объект прокси-класса, то есть myService = new MyServiceClient();? Это работает, но похоже на решение проблемы ядерной бомбы.

В качестве альтернативы, есть ли способ просто вручную получить новый токен и заменить текущий, то есть myService.ClientCredentials.Renew();?

Если для этого мне нужно создать собственный класс ClientCredentials, как мне реализовать приведенные выше примеры методов?


person Sean Hanley    schedule 09.11.2010    source источник


Ответы (2)


В моей кодовой базе мы фактически кэшируем токен, поэтому мы гарантируем, что не будем делать повторных вызовов STS. Используя тот же метод, вы определенно можете изменить его вручную, запросив другой токен, когда захотите. Вот как подключиться к 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;
    }
}

Метод GetTokenCore() вызывает STS. Когда вы вызываете GetToken(), STS будет предложено выпустить другой токен.

Судя по вашему вопросу, я предполагаю, что вы знаете, как подключиться к своим ClientCredentials из app.config.

Может быть способ установить свойство CacheIssuedTokens в файле App.config, я просто не уверен, что это не так.

person pdalbe01    schedule 16.11.2010

Не могли бы вы использовать свойство IssuedToken.MaxIssuedTokenCachingTime и установить для него значение 0?

person Robert MacLean    schedule 12.11.2010