سؤال

لدي خدمة WCF تتطلب رمزًا أمانًا صادرًا من خدمة WCF STS منفصلة. كل هذا يعمل فقط dandy. في طلبي ، أستخدم الخدمة مثل SO:

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. باستخدام نفس الطريقة ، يمكنك بالتأكيد تغييرها يدويًا مميزًا آخر كلما ترغب في ذلك. إليك كيفية ربط 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.

قد تكون هناك طريقة لتعيين خاصية CacheissuedTokens في ملف App.Config ، لست متأكدًا من إبعاد رأسي.

نصائح أخرى

ألا يمكنك استخدام IssuedToken.MaxIssuedTokenCachingTime خاصية وتعيينها على 0؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top