zoukankan      html  css  js  c++  java
  • WCF方法拦截及OperationInvoker传递参数到WCF方法的实现

    鉴于一些理由需要拦截WCF方法,比如参数的检测。一个实际的场景是CSRF防范中需要对CsrfToken的检测。
    要实现拦截,在形式上要实现两点:
    1:为WCF方法增加特性类;
    2:捕获WCF方法;
    第一点很好实现,实现一个Attribute类。第二点则可以利用WCF框架中的IOperationInvoker接口,让该Attribute类同时也实现该接口,同时在该接口方法的ApplyDispatchBehavior方法中,为dispatchOperation实现一个新的OperationInvoker。 

    public class MyOperationInterceptorAttribute : Attribute, IOperationBehavior
    {
        
        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        { }
    
        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        { }
    
        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.Invoker = new 
        }
    
        public void Validate(OperationDescription operationDescription)
        { }
    }
    
    
    public class MyInvoker : IOperationInvoker
    {
        IOperationInvoker m_OldInvoker;    
    
        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            try
            {
            //do something
                object result = m_OldInvoker.Invoke(instance, inputs, out outputParams);
                return result;
            }
            catch (Exception err)
            {
                outputs = new object[0];
            //do catch
                return null;
            }
            finally
            {
                
            }
        }
    
        public virtual object[] AllocateInputs()
        {
            return m_OldInvoker.AllocateInputs();
        }
        
        public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
        {
            return m_OldInvoker.InvokeBegin(instance, inputs, callback, state);
        }
    
        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
        {
            
            return m_OldInvoker.InvokeEnd(instance, out outputs, result);
            
        }
    
        public bool IsSynchronous
        {
            get
            {
                return m_OldInvoker.IsSynchronous;
            }
        }
    }

    如果我们将服务宿主在IIS中,则这种实现的好处是我们可以完全不需要更改配置文件就能实现对WCF方法的拦截。
    这种方式还有一种好处是,我们可以解析客户端发送过来的内容,并统一进行处理,而无需为WCF方法增加参数。如,我们对CSRF方法的时候,客户端发送过来的内容中会含有CSRFToken,传统的做法是为WCF方法一个CSRFToken的参数,如下:

    public void DoSomething(string arg0, string csrfToken)
    {
        Check(csrfToken);
        ...
    }

    并且每个需要处理CSRF的方法中都要进行如上编码,而现在只要变成:

    [MyOperationInterceptor]
    public void DoSomething(string arg0)
    {
        ...
    }

    可以看到少了参数,少了方法内的处理,当然,我们需要在MyInvoker类的Invoke方法的//do something处解析前台内容,获取CSRFToken,并进行Check,获取CSRFToken如下实现:

    string GetToken()
    {
        //rest or soap
        string token = HttpContext.Current.Request.QueryString["token"];
        if(string.IsNullOrEmpty(token))
        {
            XDocument doc = XDocument.Parse(OperationContext.Current.RequestContext.RequestMessage.ToString());
            var rootElements = (from p in doc.Descendants("root") select p).Elements();
            var args = (from p in rootElements select new {Name=p.Name.LocalName, Value=p.Value}).ToList(0;
            token = (from p in args where p.Name="token" select p.Value).First();
        }
        return token;
    }

    在这种拦截的应用中,有时候我们难免要将拦截过程中的一些内容传递到WCF方法中,如果有这样的需求,则可以将这些内容放置到OperationContet.Current.IncomingMessageProperties中,它是一个IDictionary<string, object>,当然,要对这个参数进行存取的时候,我们需要用到OperationContextScope,于是,整个MyInvoker类的Invoke方法变成如下的形式:

            try
            {
            using(OperationContextScope scope = new OperationContextScope())
            {
                //get token and check
            OperationContet.Current.IncomingMessageProperties.Add("SomeKey", SomeObjectInstance);
                //do something
                object result = m_OldInvoker.Invoke(instance, inputs, out outputParams);
                return result;
            }
            }
            catch (Exception err)
            {
                outputs = new object[0];
            //do catch
                return null;
            }
            finally
            {
                
            }

    在具体的WCF方法中,如果要使用这个SomeObjectInstance,则可以这样获得:
     SomeObjectInstance = OperationContet.Current.IncomingMessageProperties["SomeKeyas TheInstanceType;

  • 相关阅读:
    LeetCode_145.二叉树的后序遍历
    LeetCode_144.二叉树的前序遍历
    LeetCode_142.环形链表 II
    LeetCode_141.环形链表
    LINQ查询表达式---------select子句
    LINQ查询表达式---------where子句
    LINQ查询表达式---------from子句
    System.InvalidOperationException: 未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序。
    Directory.GetFiles()获取多个类型格式的文件
    System.Exception: ORA-12541: TNS: 无监听程序
  • 原文地址:https://www.cnblogs.com/luminji/p/2747834.html
Copyright © 2011-2022 走看看