如何在每个请求中将Winform自定义用户凭据传递给WCF服务?

时间:2019-03-05 14:50:30

标签: c# winforms wcf

我要实现的目标是在每个请求中将凭据/令牌传递给WCF服务。顺便说一句,此凭据不是Windows凭据,它们是从自定义数据库中获取的,并且身份验证逻辑非常简单,tenantId +用户名+密码。

我目前正在使用消息检查器将这些信息插入标头,并从服务器端检查器中获取(使用OperationContext)。

但是为了保持线程安全,我必须将请求包装在每个winform请求中,如下所示:

using (new OperationContextScope((WcfService as ServiceClient).InnerChannel))
{
   MessageHeader hdXXId = MessageHeader.CreateHeader("XXId", "CustomHeader", WinformSomeVariable.XXId);
   OperationContext.Current.OutgoingMessageHeaders.Add(hdXXId);

   _objXX = WcfService.GetXXById(id);

}

就像上面显示的那样,这很沉重,显然不是解决这种情况的明智方法。那么,有什么方法可以安全地保存此类信息,也可以在WCF检查器中获取它们?

非常感谢!

PS。感谢@Abraham Qian,我一直很傻。只需将客户检查器放在同一winform项目中即可解决此问题。

1 个答案:

答案 0 :(得分:0)

暂时忽略一下如何重构身份验证的问题。 至于如何使用IClientMessageInspector接口创建持久消息标头,以下代码段可能会有用(假设使用Channel Factory进行调用)

class Program
    {
        static void Main(string[] args)
        {
            Uri uri = new Uri("http://localhost:1300");
            IService service = ChannelFactory<IService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(uri));
            try
            {
                Console.WriteLine(service.SayHello());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }

    [ServiceContract(Namespace = "mydomain")]
    [CustomContractBehavior]
    public interface IService
    {
        [OperationContract]
        string SayHello();
    }

    public class ClientMessageLogger : IClientMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            string displayText = $"the client has received the reply:\n{reply}\n";
            Console.Write(displayText);
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
        //Add custom message header
            request.Headers.Add(MessageHeader.CreateHeader("myheader","mynamespace",2000));
            string displayText = $"the client send request message:\n{request}\n";
            Console.WriteLine(displayText);
            return null;

        }
    }

    public class CustomContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
    {
        public Type TargetContract => typeof(IService);

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            return;
        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {
            return;
        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
            return;
        }
    }