2010-11-30 63 views
7

我試圖添加一個自定義安全功能,其中客戶端向Silverlight客戶端發出的每個服務調用添加一個標記,然後該服務可以訪問此標記以控制應用程序安全系統。我試圖通過實現IClientMessageInspector接口並將其鏈接到我生成的服務客戶端來完成此操作。我沒有使用Visual Studio生成的代理,而是使用ChannelFactory創建的我自己的客戶端。我在網上找到了幾種似乎都使用2種基本方法之一的解決方案。首先通過將頭添加到呈現給IClientMessageInspector.BeforeSendRequest的消息頭集合中,然後通過使用HttpRequestMessageProperty將信息作爲屬性添加到呈現給IClientMessageInspector.BeforeSendRequest的消息中。我一直在嘗試這兩種方法而沒有任何成功。看起來,這兩種技術都成功地將數據添加到請求中,但我無法在服務器上訪問。我會補充說這對我來說是一個非常新的領域,由於經驗不足,我很可能錯過了互聯網上的答案。無法讀取WCF服務中的標頭

的代碼來生成我的客戶是:

private ISecurityAdministrationContract CreateChannel() 
    { 
     if (factory == null) 
     { 
      lock (this) 
      { 
       // Create a custom binding that uses HTTP and binary encoding. 
       var elements = new List<BindingElement>(); 
       elements.Add(new BinaryMessageEncodingBindingElement()); 
       elements.Add(new HttpTransportBindingElement()); 
       var binding = new CustomBinding(elements); 

       // Create a channel factory for the service endpoint configured with the custom binding. 
       factory = new ChannelFactory<ISecurityAdministrationContract>(binding, new EndpointAddress(SecurityAdminServiceAddress)); 

       //Add my IClientMessageInspector 
       factory.Endpoint.Behaviors.Add(new ClientSecurityInterceptor()); 
      }     
     } 
     ISecurityAdministrationContract client = factory.CreateChannel(); 
     return client; 
    } 
     } 
     ISecurityAdministrationContract client = factory.CreateChannel(); 
     return client; 
    } 

的代碼中加入我的報頭以請求是:

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) 
    { 
     //Method 1 
     MessageHeader header = MessageHeader.CreateHeader("MyFirstAuthentication", "ns", "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEEE"); 
     request.Headers.Add(header); 

     //Method 2 
     HttpRequestMessageProperty httpRequestMessage; 
     httpRequestMessage = new HttpRequestMessageProperty(); 
     httpRequestMessage.Headers["MySecondAuthentication"] = "11111111-2222-3333-4444-5555555555555"; 
     request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage); 

     return null; 
    } 

上面的代碼實現了這兩種技術。

由小提琴手被困的服務電話是:(NB HTTP與ht_tp COS現場更換不會讓我張貼hyoerlinks)

POST ht_tp://127.0.0.1:6785/SecurityAdministrationRelayService.svc/HTTP/1.1 接受:/ 的Referer:ht_tp://ipv4.fiddler:6785 /的ClientBin/Civica.Housing.xap 接受語言:EN-GB 的Content-Length:400 內容類型:應用/ soap + msbin1 MySecondAuthentication:11111111-2222-3333-4444-5555555555555 Accep t-Encoding:gzip,deflate User-Agent:Mozilla/4.0(compatible; MSIE 8.0; Windows NT 5.1;三叉戟/ 4.0; GTB5; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727) 主持人:127.0.0.1:6785 連接:保持活動 雜注:無緩存

V_ 小號 _a_V_D Ahttp://tempuri.org/ISecurityAdministrationContract/CreateAdvocateDߔ_9紅箭-9反坦克導彈-d,d * @MyFirstAuthentication _ns%AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEEED _ @的http:/ /ipv4.fiddler:6785/SecurityAdministrationRelayService.svc/ V @_CreateAdvocate_ http://tempuri.org/@advocateVO {「Id」:0,「UserId」:4,「AdvocateForId」:8,「ValidFrom」:「/ Date(1291127869690 + 0000)/」,「ValidTo 「:null} __

這似乎確實包含了這兩種技術的標記信息。

當我嘗試提取此信息時,服務器出現問題。我已經實現了一個IOperationInvoker,並試圖在IncomingMessageHeaders中找到頭,但沒有任何成功。我也在IncomingMessageProperties中搜索,但我看不到任何我添加的頭部細節。 這是我使用的IOperationInvoker代碼:

public object Invoke(object instance, object[] inputs, out object[] outputs) 
    { 
     PreInvoke(instance, inputs); 
     object returnedValue = null; 
     object[] outputparams = new object[] { }; 
     Exception exception = null; 
     try 
     { 
      returnedValue = originalInvoker.Invoke(instance, inputs, out outputparams); 
      outputs = outputparams; 
      return returnedValue; 
     } 
     catch (Exception e) 
     { 
      exception = e; throw; 
     } 
     finally 
     { 
      PostInvoke(instance, returnedValue, outputparams, exception); 
     } 
    } 


    protected virtual void PreInvoke(object instance, object[] inputs) 
    { 
     //Look for header directly 
     int index = System.ServiceModel.OperationContext.Current.IncomingMessageHeaders.FindHeader("MyFirstAuthentication", "ns"); 

     //Search via enumerator 
     foreach (var header in System.ServiceModel.OperationContext.Current.IncomingMessageHeaders) 
     { 
     } 

    } 

的FindHeader返回-1,同時枚舉發現5頭,即; 'Action','MessageID','ReplyTo','VsDebuggerCausalityData'&'To'。

的OperationContext.Current.IncomingMessageProperties集合包含4項,分別是:「經由」,「安全」,「編碼器」 &「System.ServiceModel.Channels.RemoteEndpointMessageProperty」

事實上,如果我註釋掉線在我的客戶端中,將IClientMessageInspector添加到ClienChannel,然後通過省略添加的細節來報告fiddler報告的更改,但傳入消息上的標頭和屬性集合保持不變。

任何關於如何獲取這些信息的想法,或者爲什麼它不作爲IncomingMessage的一部分呈現,都會非常感激地收到。

回答

6

我已經回答了我自己的問題。上述任何代碼都沒有問題,只需將其鏈接到正確的位置即可。在我的完整解決方案中,我從Silverlight客戶端調用服務,然後調用第二個服務。令人尷尬的是,我將IOperationInvoker鏈接到了第二個服務(doh)中。當我將它鏈接到中間服務時,標題可按預期得到。

讀取值的代碼是:

  int index = OperationContext.Current.IncomingMessageHeaders.FindHeader("MyFirstAuthentication", "ns"); 
      if (index >= 0) 
      { 
       string value = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(index); 
      } 
2

您可以使用以下方法來訪問標頭值:

var headers = OperationContext.Current.IncomingMessageProperties["httpRequest"]; 
var apiToken = ((HttpRequestMessageProperty)headers).Headers["<YourHeaderKey>"];