Как придумать обновление токена безопасности для службы WCF?
-
30-09-2019 - |
Вопрос
У меня есть услуга 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 для этого, как бы я реализовал приведенные выше примеры методов?
Решение
В моей кодовой базе мы на самом деле кэшируем токен, поэтому мы гарантируем, что не делаем повторяющихся вызовов в STS. Используя тот же метод, вы определенно можете изменить его вручную запрашивать другой токен, когда пожелаете. Вот как зацепить клиентские кадры:
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 (), ST будет предложено выпустить другой токен.
Из вашего вопроса я предполагаю, что вы знаете, как зацепить свои клиенты из App.config.
В файле App.config может быть способ установить свойство CacheissuedTokens, я просто не уверен в пути от макула моей головы.
Другие советы
Не могли бы вы использовать IssuedToken.MaxIssuedTokenCachingTime
свойство и установить его на 0?