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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM