我有一个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类来执行此操作,我将如何实现上述示例方法?
答案 0 :(得分: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属性,我只是不确定是不是最重要的。
答案 1 :(得分:1)
您是否可以使用IssuedToken.MaxIssuedTokenCachingTime
属性并将其设置为0?