WCF消息拦截,利用消息拦截做身份验证服务

本文参考  http://blog.csdn.net/tcjiaan/article/details/8274493  博客而写

添加对信息处理的类

 /// <summary>
    /// 消息拦截
    /// </summary>
    public class MyMessageInspector:IClientMessageInspector,IDispatchMessageInspector
    {
        //用户名密码
        static private  string uName = "admin";
        static private  string pWord = "admin";
        //初始化
        public MyMessageInspector() { }
        public MyMessageInspector(string name, string pass)
        {
            uName = name;
            pWord = pass;
        }

        //客户端接收的信息之后的处理
        void IClientMessageInspector.AfterReceiveReply(ref Message replaly, object correlationState)
        {
            Console.WriteLine("客户端接收的信息:
{0}",replaly.ToString());
        }
        //客户端发送消息之前的处理
        object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            //Console.WriteLine("客户端发送请求前的SOAP消息:
{0}", request.ToString());
            MessageHeader hdUserName = MessageHeader.CreateHeader("u", "fuck", uName);
            MessageHeader hdPassWord = MessageHeader.CreateHeader("p", "fuck", pWord);
            request.Headers.Add(hdUserName);
            request.Headers.Add(hdPassWord);

            return null;  
            
        }
        //服务 端接收到消息之后的处理
        object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            //Console.WriteLine("服务器端:接收到的请求:
{0}", request.ToString());
            string un = request.Headers.GetHeader<string>("u", "fuck");
            string ps = request.Headers.GetHeader<string>("p", "fuck");
            if (un == "admin" && ps == "abcd")
            {
                Console.WriteLine("用户名和密码正确。");
            }
            else
            {
                throw new Exception("验证失败,滚吧!");
            }
            return null; 
            
        }
        //服务端在发送消息之前的处理
        void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState)
        {
            Console.WriteLine("服务器即将作出以下回复:
{0}", reply.ToString());
        }
    }

以上的用户名和密码都是固定值 ,你可以查询数据库,判断  是否有此用户,来保证 身份安全性

添加插入结结点的方法类

/// <summary>
    /// 插入到终结点的Behavior  
    /// </summary>
    public class MyEndPointBehavior : IEndpointBehavior
    {
        //用户名密码
        private string UserName = "admin";
        private string PassWord = "admin";

        public MyEndPointBehavior() { }
        public MyEndPointBehavior(string name,string pass) 
        {
            UserName = name;
            PassWord = pass;
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            return;
        }
        
        public void ApplyClientBehavior(ServiceEndpoint endopint ,ClientRuntime clientRuntime)
        {
            // 植入“偷听器”客户端
            clientRuntime.MessageInspectors.Add(new MyMessageInspector(UserName,PassWord));
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            // 植入“偷听器” 服务器端  
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyMessageInspector(UserName,PassWord));
        }
        public void Validate(ServiceEndpoint endpoint)
        {
            return;
        }
    }

上面类的用户名和密码是由客户端传过来的,如果客户端没有传过来则默认都为 "admin"

注,以上两个类在服务 端和客户端都需要被引用 

宿主程序 ,采用控制台应用程序 

 static void Main(string[] args)
        {
            Uri baseAddress = new Uri("http://localhost:1378/services");
            using (ServiceHost host = new ServiceHost(typeof(WCF_LanJie_Lib.Service), baseAddress)) 
            {
                WSHttpBinding bind = new WSHttpBinding();
                host.AddServiceEndpoint(typeof(WCF_LanJie_Lib.IService),bind,"/Test");
                // 添加服务描述  
                host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
               
                // 把自定义的IEndPointBehavior插入到终结点中  
                foreach (var endpont in host.Description.Endpoints)
                {
                    endpont.Behaviors.Add(new WCF_LanJie_Lib.MyEndPointBehavior());
                }

                try
                {
                    // 打开服务  
                    host.Open();
                    Console.WriteLine("服务已启动。");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.ReadKey(); 
            }
        }

其中,添加服务描述 HttpGetEnabled = true 是用于打开元数据 ,可供访问和下载

foreach ()循环是用来把服务 终结点和消息拦截的类相联系起来

客户端

客户端也是一个控件台应用程序

 static void Main(string[] args)
        {
            Client.ServiceClient cli = new Client.ServiceClient();//引用
            //定义一个消息拦截类,初始化
            WCF_LanJie_Lib.MyEndPointBehavior mypoint = new MyEndPointBehavior("admin", "abcd");
            // 把自定义的IEndPointBehavior插入到终结点中  
            cli.Endpoint.Behaviors.Add(mypoint);
            //服务端调用方法
            Console.WriteLine(cli.GetDate("qwe"));
            Console.ReadLine();
        }

其中  字符串 "admin"即为用户名和密码,你可以根据程序 的用户名和密码对基进行修改!!!

到此,一个简单的消息拦截,身份验证就完成 了!

原文地址:https://www.cnblogs.com/chcong/p/4323134.html