2012-04-17 45 views
5

我正在爲某些STS服務構建一個客戶端,並且現在我試圖向WCF消息添加一個頭部。在我對RequestSecurityToken的調用中,我必須包含一個UsernameToken。操縱WCF頭部細節

我不知道該如何實現。目前我定義了一個端點行爲和一個消息檢查器(花了我足夠長的時間來發現那些...)。在後者的BeforeSendRequest()中,我創建了一個派生自MessageHeader的自定義類「安全」的對象。安全性包括UsernameToken的一個實例。

public class MessageInspector : IClientMessageInspector { 

public object BeforeSendRequest(ref Message request, IClientChannel channel) { 
    Security uns = new Security(); 
    uns.UsernameToken = new UsernameToken(); 

    // ... 

    var Header = new MessageHeader<Security>(uns); 
    var untyped = Header.GetUntypedHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
    request.Headers.Add(untyped); 
    return null; 
} 
} 

public class Security : MessageHeader { 
public UsernameToken UsernameToken = new UsernameToken(); 

public override string Name { 
    get { return "Security"; } 
} 

public override string Namespace { 
    get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; } 
} 
} 

public class UsernameToken { 
public String Username = ""; 
public Password Password = new Password(); 
} 

這就是被序列

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Header> 
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:RequestSecurityToken</Action> 
    <Security xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
     <UsernameToken xmlns="http://schemas.datacontract.org/2004/07/Tarifrechner.Kfz"> 
     <Password> 
      <Type>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText</Type> 
      <password>******</password> 
     </Password> 
     <Username>******</Username> 
     </UsernameToken> 
    </Security> 
    </s:Header> 
    <s:Body /> 
</s:Envelope> 

特別的UsernameToken的命名空間似乎是錯誤的。我知道它來自數據協定序列化,但我需要一個不同的命名空間。

這是我想序列化的數據看起來像

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:soap="..."> 
    <soap:Header> 
    <Security xmlns:q1="http://www.bipro.net/namespace" xsi:type="q1:UserNameSecurity" 
      xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
     <UsernameToken> 
     <Username>******</Username> 
     <Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">******</Password> 
     </UsernameToken> 
    </Security> 
    <wsa:Action>urn:RequestSecurityToken</wsa:Action> 
    <wsse:Security> 
     <wsu:Timestamp wsu:Id="Timestamp-b9dd599d-5901-451d-8321-6a309091f273"> 
     <wsu:Created>2012-03-11T16:02:56Z</wsu:Created> 
     <wsu:Expires>2012-03-11T16:07:56Z</wsu:Expires> 
     </wsu:Timestamp> 
    </wsse:Security> 
    </soap:Header> 
    <soap:Body> 
    <RequestSecurityToken xmlns="http://schemas.xmlsoap.org/ws/2005/02/trust"> 
     <TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</TokenType> 
     <RequestType> 
     http://schemas.xmlsoap.org/ws/2005/02/trust/Issue 
     </RequestType> 
    </RequestSecurityToken> 
    </soap:Body> 
</soap:Envelope> 

是我對正確的方法是什麼?我該如何操縱諸如頭部細節的命名空間之類的東西,或者數據是否被序列化爲屬性或元素?

更新


正如拉吉斯拉夫已經指出的那樣,我沒有實現像用戶名令牌自己的類。我這樣做只是因爲我對WCF的知識非常有限。

現在,我發現,WS2007HttpBinding配置爲使用SecurityMode.TransportWithMessageCredential並且將EstablishSecurityContext設置爲false會生成幾乎所需的XML。我應該怎麼知道?

但還有一個問題:我的請求有一個空的body元素,我要生成的請求在body元素內部有一個RequestSecurityToken元素。有誰知道,我怎麼能做到這一點?

使用EstablishSecurityContext = true有助於同時將我的Soap-Action從所需的「urn:RequestSecurityToken」更改爲非工作的「http://docs.oasis-open.org/ws-sx/ws -trust/200512/RST/SCT」。


我很感謝任何答案!

非常感謝!

比約恩

+1

HTTP:/ /stackoverflow.com/questions/5228430/how-to-add-attribute-to-wcf-message-header-with-messageheader-createheader-met 希望這會有所幫助 – v00d00 2012-04-17 12:22:09

+3

爲什麼你要手動做這個?如果您設置WCF安全配置,它會爲您添加這些標頭。 – 2012-04-17 12:23:13

回答

0

有幾種不同的方式取決於你需要如何控制標題和內容,你需要插入頁眉標頭添加到郵件。

在您的應用程序代碼中,您可以圍繞請求創建OperationContextScope以更改某些請求屬性。在OperationContextScope內部,您有一個OperationContext.Current的有效實例,它允許通過OutgoingMessageHeaders集合操縱消息標題。使用這種方法可以將頭文件的控制深入到應用程序代碼中。你需要負責在任何需要的地方複製適當的代碼。

Thesetwo鏈路(從別人的WCF團隊)談論這個更詳細的一噸的代碼示例:

1

一種替代方法是定義一個MessageContract類型爲你的要求,它允許你定義SOAP消息的頭部和主體中顯示的內容並調整所使用的名稱空間。例如,考慮下面的服務定義:

[ServiceContract] 
    public interface IMyService 
    { 
     [OperationContract] 
     MyResponse DoSomething(MyRequest request); 
    } 

    public class MyService : IMyService 
    { 
     public MyResponse DoSomething(MyRequest request) 
     { 
      return new MyResponse() 
      { 
       Details = "Service did something awesome.", 
       Timestamp = DateTime.Now 
      }; 
     } 
    } 

    [MessageContract(IsWrapped = true, WrapperNamespace = "http://myservice/messages/")] 
    public class MyRequest 
    { 
     [MessageHeader(Namespace = "http://myservice/security")] 
     public string TokenThingy 
     { 
      get; 
      set; 
     } 
    } 

    [MessageContract(IsWrapped = true, WrapperNamespace = "http://myservice/messages")] 
    public class MyResponse 
    { 
     [MessageBodyMember] 
     public string Details 
     { 
      get; 
      set; 
     } 

     [MessageBodyMember] 
     public DateTime Timestamp 
     { 
      get; 
      set; 
     } 
    } 

發送請求產生以下SOAP:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Header> 
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IMyService/DoSomething</Action> 
    <h:TokenThingy xmlns:h="http://myservice/security">fda</h:TokenThingy> 
    </s:Header> 
    <s:Body> 
    <MyRequest xmlns="http://myservice/messages/" /> 
    </s:Body> 
</s:Envelope> 

而從服務的響應是這樣的:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Header /> 
    <s:Body> 
    <MyResponse xmlns="http://myservice/messages"> 
     <Details xmlns="http://tempuri.org/">Service did something awesome.</Details> 
     <Timestamp xmlns="http://tempuri.org/">2012-05-04T17:04:36.5980424-04:00</Timestamp> 
    </MyResponse> 
    </s:Body> 
</s:Envelope>