当前位置:  开发笔记 > 运维 > 正文

SCT过期后续订WCF客户端?

如何解决《SCT过期后续订WCF客户端?》经验,为你挑选了2个好方法。

我使用安全模式"TransportWithMessageCredential"将WCF用于soap端点.

WCF客户端/服务器使用SCT(安全上下文令牌)来维护安全连接,并且它在一般情况下按预期工作.

但是,在一段时间不活动后,SCT将过期,下一个方法调用将导致MessageSecurityException:

从另一方收到了无担保或不正确安全的故障.请参阅内部FaultException以获取故障代码和详细信息

内部异常:

邮件无法处理.这很可能是因为" http://tempuri.org/IMyService/MyMethod "操作不正确,或者因为邮件包含无效或过期的安全上下文令牌,或者因为绑定之间存在不匹配.如果服务由于不活动而中止了通道,则安全上下文令牌将无效.要防止服务中止空闲会话,请过早增加服务端点绑定的接收超时.

在后续调用中,当我看到CommunicationState出现故障时,我会更新连接.但在进行方法调用之前,我无法找到预先检查SCT是否已过期的方法.



1> Troels Thoms..:

您可以使用委托来解决您的问题.这将允许安全地调用操作,如果失败,则捕获异常,构造新的服务实例并再次执行操作.

using System;
using System.ServiceModel;
using System.ServiceModel.Security;

public static class Service
{
    private static IService _service;

    public static void Invoke(Action action)
    {
        try
        {
            action(_service);
        }
        catch (MessageSecurityException)
        {
            if (_service.State != CommunicationState.Faulted)
            {
                throw;
            }

            _service.Abort();
            _service = CreateFreshInstance();

            action(_service);
        }           
    }
}

然后,您可以调用您的帮助程序类Service.Invoke(s => s.Method());来调用IService.Method().



2> Steve Platz..:

在第一个答案的基础上,我想到了此解决方案,该解决方案通常包装由svcutil.exe创建的自动生成的客户端代理:

public class ProxyWrapper where T : ICommunicationObject
{
    private T _service;

    public ProxyWrapper()
    {
        _service = CreateNewInstance();
    }

    public void Invoke(Action action)
    {
        try
        {
            action(_service);
        }
        catch (MessageSecurityException)
        {
            if (_service.State != CommunicationState.Faulted)
            {
                throw;
            }

            _service.Abort();
            _service = CreateNewInstance();

            action(_service);
        }
    }

    public TResult Invoke(Func func)
    {
        try
        {
            return func(_service);
        }
        catch (MessageSecurityException)
        {
            if (_service.State != CommunicationState.Faulted)
            {
                throw;
            }

            _service.Abort();
            _service = CreateNewInstance();

            return func(_service);
        }
    }

    private T CreateNewInstance()
    {
        Type type = typeof(T);
        return (T)type.GetConstructor(Type.EmptyTypes).Invoke(null);
    }
}

要使用此功能,您需要做的是:

ProxyWrapper client = new ProxyWrapper();
client.Invoke(s => s.SomeAction());
int val = client.Invoke(s => s.ReturnsAnInteger());

注意:由于我仅使用默认的构造函数作为客户端代理,因此就可以了。

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有