如何强制刷新 WCF 服务的安全令牌?

发布于 2024-10-02 01:44:13 字数 691 浏览 1 评论 0原文

我有一个 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 类来执行此操作,我将如何实现上述示例方法?

I have a WCF Service that requires a security token issued by a separate WCF STS Service. This all works just dandy. In my application, I use the service like so:

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

The STS Service is called to get a token and the token is used to call the service method DoStuff.

Once the initial handshake is over, though, the myService object has the token cached and re-uses it until it expires. This is fine behavior and all, but how would I force it to refresh the token?

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

Such that if I called DoStuff() again it would know it needs to go to the STS again much as it did the first time.

Am I stuck just making a new proxy class object, i.e. myService = new MyServiceClient();? This works but it seems like the nuclear bomb solution.

Alternatively, is there a way to just manually get a new token and replace the current one, i.e. myService.ClientCredentials.Renew();?

If I have to make a custom ClientCredentials class to do this, how would I implement the above example methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南巷近海 2024-10-09 01:44:13

在我的代码库中,我们实际上缓存了令牌,因此我们确保不会重复调用 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 属性,但我只是不确定有什么方法可以解决。

In my codebase, we actually cache the token so we ensure that we don't make repeated calls to the STS. Using the same method, you could definitely alter it manually request another token whenever you wish. Here's how to hook into 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;
    }
}

The GetTokenCore() method is where the STS gets called. When you call GetToken(), the STS will be asked to issue another token.

From your question, I assume you know how to hook into your ClientCredentials from the app.config.

There might be a way of setting the CacheIssuedTokens property in the App.config file, I'm just not sure of a way off the top of my head.

空心空情空意 2024-10-09 01:44:13

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

Could you not use the IssuedToken.MaxIssuedTokenCachingTime property and set it to 0?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文