如何在每个请求中将 winform 自定义用户凭据传递给 WCF 服务? [英] How to pass winform custom user credentials to WCF services in every requests?

查看:27
本文介绍了如何在每个请求中将 winform 自定义用户凭据传递给 WCF 服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What I'm trying to achieve is passing credentials/token to WCF services in every requests. BTW, this credential IS NOT windows credentials, they are fetched from custom db, and the authentication logic is quite simple, tenantId+username+password.

我目前正在使用消息检查器在标头中插入这些类型的信息,并从服务器端检查器中获取它们(使用 OperationContext).

I'm currently using message inspector to insert these kind of information in the headers and fetch them from server-side inspector(using OperationContext).

但是为了保持线程安全,我必须像这样将请求包装在每个 winform 请求中:

But in order to stay thread-safe,I have to wrap the requests in every winform request like this:

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 检查器中获取它们?

Like showed above, this is quite heavy and obviously not a smart way to handle this situation. So is there any way to hold these kind of information safely and can as well fetch them in the WCF Inspectors?

非常感谢!

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

PS. Thanks to @Abraham Qian, I was being silly the whole time. Just put the client inspector within the same winform project will solve this issue.

推荐答案

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

Just ignore the question of how to refactor your authentication for a moment. As for how to use the IClientMessageInspector interface to create a persistent message header, the following code snippet might be useful (Assume that invocation by using 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;
        }
    }

这篇关于如何在每个请求中将 winform 自定义用户凭据传递给 WCF 服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆