Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Thread.CurrentPrincipal未在WCF客户端回调中持久化_C#_Multithreading_Wcf_Wcf Security_Wcf Callbacks - Fatal编程技术网

C# Thread.CurrentPrincipal未在WCF客户端回调中持久化

C# Thread.CurrentPrincipal未在WCF客户端回调中持久化,c#,multithreading,wcf,wcf-security,wcf-callbacks,C#,Multithreading,Wcf,Wcf Security,Wcf Callbacks,我有一个通过netTcpBinding的双工WCF服务,该服务使用订阅模式,其中客户端 将通过使用subscribe/Unsubscribe方法的回调实现来订阅服务 该服务有一个自定义的IAuthorizationPolicy,用于从数据库和 在IAuthorizationPolicy.Evaluate()方法中将默认线程主体设置为自定义主体 该服务在IIS 7.5中作为服务运行,位于LOCALSYSTEM标识下的Windows 7 首先,以下是客户端(WinForms)如何对用户进行身份验证:

我有一个通过netTcpBinding的双工WCF服务,该服务使用订阅模式,其中客户端 将通过使用subscribe/Unsubscribe方法的回调实现来订阅服务

该服务有一个自定义的IAuthorizationPolicy,用于从数据库和 在IAuthorizationPolicy.Evaluate()方法中将默认线程主体设置为自定义主体

该服务在IIS 7.5中作为服务运行,位于LOCALSYSTEM标识下的Windows 7

首先,以下是客户端(WinForms)如何对用户进行身份验证:

  • 显示登录表单以请求凭据
  • 在不同端点上调用另一个身份验证服务以 验证用户凭据
  • 使用AppDomain.SetThreadPrincipal设置默认线程主体
  • 我面临的问题是,在回调线程中,并且只有在回调线程中,在未传播身份验证后设置的匿名GenericPrincipal对象和我的自定义主体中,Thread.CurrentPrincipal才被重置


    更新:如果我将securityMode和clientCredentialType设置为“无”,主体将按预期传播,显然这与安全配置有关,我尝试了很多配置组合,但都没有成功


    更新:我已经包括了一份复制该问题的报告

    该解决方案是直接配置和运行的,只需点击几次,占用您宝贵的几分钟时间,它包含5个项目:

  • PM.Services-WCF服务项目
  • PM.Contracts-包含服务合同的库
  • 客户端/广播机-控制台应用程序通过服务向其他客户端广播
  • 客户端/侦听器-订阅服务/侦听广播的控制台应用程序(这是Thread.CurrentPrincipal重置的地方)
  • 客户端/Shared-两个客户端之间共享的库,包含回调实现和服务创建代码
  • 要在您的计算机上配置服务(假设已在计算机上启用IIS7或更高版本),解决方案根文件夹包含两个批处理文件:

    InstallService.bat:此批将:

    • 在计算机上启用以下windows功能及其父功能(如果尚未启用): Windows通信基础HTTP激活和Windows 通信基础非HTTP激活,启用WCF和 net.tcp

    • 将在TrustedPeople存储中创建和添加服务证书

    • 将为将收听的服务创建网站:7359 (http)和7357(net.tcp)

    • 将在LOCALSYSTEM标识下创建应用程序池(以避免 测试期间的许可问题)

    • 将在c:\inetpub\WCFCallbackSample中创建一个文件夹,并将服务输出复制到其中

    卸载服务.bat:此批将:

    • 从TrustedPeople存储中删除服务证书

    • 卸载服务网站

    • 删除网站文件夹

    运行示例解决方案:

    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IFinanceServiceCallback))]
    public interface IFinanceService : IServiceContract, ISupportCallback // <-- Interface that defines Subscribe and Unsubscribe methods
    {
        [OperationContract]
        void DuplexMessageTest(string text);
    }
    
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] 
    public class FinanceService : IFinanceService
    {
        // Subscription boilerplate code
        private static readonly 
            DuplexServiceSubscriptionManager<IFinanceServiceCallback> _subscriptionManager = new DuplexServiceSubscriptionManager<IFinanceServiceCallback>();
    
        public bool Subscribe()
        {
            return _subscriptionManager.Subscribe();
        }
    
        public bool Unsubscribe()
        {
            return _subscriptionManager.Unsubscribe();
        }
    
        // A test method for simulation
        public void DuplexMessageTest(string text)
        {
            _subscriptionManager.InvokeCallbackMethod(callback => callback.OnDuplexTest(text));
        }
    
    [CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Single,  AutomaticSessionShutdown=true)]
    public class FinanceServiceCallbackSubscription :  BaseServiceSubscription<IFinanceService>, IFinanceServiceCallback
    {
        public FinanceServiceCallbackSubscription() : base()
        {
        }
    
        public delegate void DuplexTestEventHandler(string message);
    
        public event DuplexTestEventHandler DuplexTest;
    
        public void OnDuplexTest(string message)
        {
            -->> At this point, the Thread.CurrentPrincipal is reset <<--
            if (DuplexTest != null)
                DuplexTest(message);
        }
    }
    
    • 构建解决方案

    • 使用InstallService.bat安装服务

    • 调试/运行解决方案以运行两个服务使用者 (客户端\广播机,客户端\侦听器)

    • 从广播公司发送消息

    • 在侦听器中,您将注意到回调线程标识 (打印在控制台上)与主线程的标识不同 由SetThreadPrincipal在应用程序启动时设置


    起始邮政编码:

    服务接口:

    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IFinanceServiceCallback))]
    public interface IFinanceService : IServiceContract, ISupportCallback // <-- Interface that defines Subscribe and Unsubscribe methods
    {
        [OperationContract]
        void DuplexMessageTest(string text);
    }
    
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] 
    public class FinanceService : IFinanceService
    {
        // Subscription boilerplate code
        private static readonly 
            DuplexServiceSubscriptionManager<IFinanceServiceCallback> _subscriptionManager = new DuplexServiceSubscriptionManager<IFinanceServiceCallback>();
    
        public bool Subscribe()
        {
            return _subscriptionManager.Subscribe();
        }
    
        public bool Unsubscribe()
        {
            return _subscriptionManager.Unsubscribe();
        }
    
        // A test method for simulation
        public void DuplexMessageTest(string text)
        {
            _subscriptionManager.InvokeCallbackMethod(callback => callback.OnDuplexTest(text));
        }
    
    [CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Single,  AutomaticSessionShutdown=true)]
    public class FinanceServiceCallbackSubscription :  BaseServiceSubscription<IFinanceService>, IFinanceServiceCallback
    {
        public FinanceServiceCallbackSubscription() : base()
        {
        }
    
        public delegate void DuplexTestEventHandler(string message);
    
        public event DuplexTestEventHandler DuplexTest;
    
        public void OnDuplexTest(string message)
        {
            -->> At this point, the Thread.CurrentPrincipal is reset <<--
            if (DuplexTest != null)
                DuplexTest(message);
        }
    }
    
    [ServiceContract(SessionMode=SessionMode.Required,CallbackContract=typeof(IFinanceServiceCallback))]
    公共接口IFinanceService:IServiceContract,ISupportCallback//callback.OnDuplexTest(text));
    }
    
    回调实现:

    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IFinanceServiceCallback))]
    public interface IFinanceService : IServiceContract, ISupportCallback // <-- Interface that defines Subscribe and Unsubscribe methods
    {
        [OperationContract]
        void DuplexMessageTest(string text);
    }
    
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] 
    public class FinanceService : IFinanceService
    {
        // Subscription boilerplate code
        private static readonly 
            DuplexServiceSubscriptionManager<IFinanceServiceCallback> _subscriptionManager = new DuplexServiceSubscriptionManager<IFinanceServiceCallback>();
    
        public bool Subscribe()
        {
            return _subscriptionManager.Subscribe();
        }
    
        public bool Unsubscribe()
        {
            return _subscriptionManager.Unsubscribe();
        }
    
        // A test method for simulation
        public void DuplexMessageTest(string text)
        {
            _subscriptionManager.InvokeCallbackMethod(callback => callback.OnDuplexTest(text));
        }
    
    [CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Single,  AutomaticSessionShutdown=true)]
    public class FinanceServiceCallbackSubscription :  BaseServiceSubscription<IFinanceService>, IFinanceServiceCallback
    {
        public FinanceServiceCallbackSubscription() : base()
        {
        }
    
        public delegate void DuplexTestEventHandler(string message);
    
        public event DuplexTestEventHandler DuplexTest;
    
        public void OnDuplexTest(string message)
        {
            -->> At this point, the Thread.CurrentPrincipal is reset <<--
            if (DuplexTest != null)
                DuplexTest(message);
        }
    }
    
    [CallbackBehavior(UseSynchronizationContext=false,ConcurrencyMode=ConcurrencyMode.Single,AutomaticsSessionShutdown=true)]
    公共类FinanceServiceCallbackSubscription:BaseServiceSubscription,IFinanceServiceCallback
    {
    public FinanceServiceCallbackSubscription():base()
    {
    }
    公共委托无效DuplexTestEventHandler(字符串消息);
    公共事件双工测试;
    公共无效OnDuplexTest(字符串消息)
    {
    
    -->>此时,Thread.CurrentPrincipal被重置。您的服务是如何配置的?@ErikFunkenbusch更新了服务配置问题。您的代码是在IIS、应用程序还是服务中运行的?它运行的进程的标识是什么?服务是如何创建的?哦,仅供参考,您的非活动超时没有按照您的想法执行确实如此……这是一个被广泛误解的设置,与receiveTimeout一起工作。receiveTimeout控制在中断连接之前无法接收消息的最长时间。inactivityTimeout控制发送心跳消息的时间(指定时间的一半)@ErikFunkenbusch我已经包括了创建服务的工厂方法。