8

我有一个 WCF 服务,它需要由单独的 WCF STS 服务颁发的安全令牌。这一切都只是花花公子。在我的应用程序中,我像这样使用该服务:

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

调用 STS Service 获取令牌,并使用令牌调用服务方法 DoStuff。

但是,一旦初始握手结束,myService对象就会缓存令牌并重新使用它,直到它过期。这是很好的行为,但我将如何强制它刷新令牌?

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

这样,如果我再次调用 DoStuff(),它就会知道它需要再次访问 STS,就像第一次那样。

我是否只是制作一个新的代理类对象,即myService = new MyServiceClient();?这行得通,但它似乎是核弹解决方案。

或者,有没有办法手动获取新令牌并替换当前令牌,即myService.ClientCredentials.Renew();

如果我必须创建一个自定义 ClientCredentials 类来执行此操作,我将如何实现上述示例方法?

4

2 回答 2

4

在我的代码库中,我们实际上缓存了令牌,因此我们确保不会重复调用 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 发行另一个令牌。

根据您的问题,我假设您知道如何从 app.config 连接到您的 ClientCredentials。

可能有一种方法可以在 App.config 文件中设置 CacheIssuedTokens 属性,我只是不确定有什么办法。

于 2010-11-16T16:23:33.387 回答
1

您不能使用该IssuedToken.MaxIssuedTokenCachingTime属性并将其设置为 0 吗?

于 2010-11-12T07:59:40.133 回答