2012-04-17 33 views
5

Tôi đang xây dựng một khách hàng cho một số dịch vụ STS và trong hơn một ngày bây giờ tôi đang cố gắng thêm Tiêu đề vào một thông báo WCF. Trong lời gọi đến RequestSecurityToken, tôi phải bao gồm một UsernameToken.Thao tác chi tiết tiêu đề WCF

Tôi không chắc chắn cách thực hiện điều đó. Hiện tại tôi đã xác định một hành vi điểm cuối và một thanh tra thư (đã cho tôi đủ thời gian để khám phá những người đó ...). Trong BeforeSendRequest() của phần sau, tôi tạo một đối tượng của lớp tùy chỉnh 'Security' có nguồn gốc từ MessageHeader. Bảo mật bao gồm một phiên bản của 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(); 
} 

Đây là những gì đang được serialized

<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> 

Đặc biệt là không gian tên của UsernameToken có vẻ là sai. Tôi biết nó xuất phát từ việc serialization hợp đồng dữ liệu nhưng tôi cần một không gian tên khác.

Đây là những gì tôi muốn các dữ liệu tuần tự để trông giống như

<?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> 

Là cách tiếp cận của tôi về phải không? Và làm cách nào tôi có thể thao tác những thứ như không gian tên của chi tiết tiêu đề hoặc liệu dữ liệu đang được tuần tự hóa dưới dạng thuộc tính hoặc phần tử?

Cập nhật


Như Ladislav đã lưu ý, tôi không cần phải thực hiện các lớp học như UsernameToken bản thân mình. Tôi đã làm điều đó chỉ vì kiến ​​thức của tôi về WCF rất hạn chế.

Lúc này, tôi đã phát hiện ra rằng WS2007HttpBinding, được cấu hình để sử dụng SecurityMode.TransportWithMessageCredential và với thiết lập EstablishSecurityContext thành false tạo ra hầu hết XML mà tôi đang tìm kiếm. Làm thế nào tôi nên biết điều đó?

Nhưng còn một vấn đề nữa: Yêu cầu của tôi có phần tử thân trống, trong đó yêu cầu tôi muốn tạo, có phần tử RequestSecurityToken bên trong phần tử nội dung. Có ai biết, làm thế nào tôi có thể đạt được điều đó?

Sử dụng EstablishSecurityContext = true giúp nhưng đồng thời thay đổi Soap-Action của tôi từ mong muốn "urn: RequestSecurityToken" thành "không hoạt động": http://docs.oasis-open.org/ws-sx/ws -trust/200512/RST/SCT ".


Tôi đánh giá cao mọi câu trả lời!

Cảm ơn rất nhiều!

Björn

+1

http://stackoverflow.com/questions/5228430/how-to-add-attribute-to-wcf-message-header-with-messageheader-createheader-met Hy vọng điều này sẽ giúp – v00d00

+3

Tại sao bạn làm điều này theo cách thủ công? Nếu bạn đặt cấu hình bảo mật WCF, nó sẽ thêm các tiêu đề đó cho bạn. –

Trả lời

0

Có một vài cách khác nhau để thêm tiêu đề để nhắn tùy thuộc vào cách bạn cần phải kiểm soát các nội dung tiêu đề và nơi bạn cần phải chèn tiêu đề.

Trong mã ứng dụng của bạn, bạn có thể tạo một OperationContextScope xung quanh yêu cầu để thay đổi một số thuộc tính yêu cầu. Bên trong một OperationContextScope, bạn có một phiên bản hợp lệ của OperationContext.Current, cho phép thao tác các tiêu đề thư thông qua bộ sưu tập OutgoingMessageHeaders. Việc sử dụng phương pháp này sẽ kiểm soát chặt chẽ các tiêu đề vào mã ứng dụng. Bạn sẽ phải chịu trách nhiệm sao chép mã thích hợp ở bất cứ đâu cần.

Thesetwo liên kết (từ một ai đó trong nhóm WCF) nói chuyện về vấn đề này chi tiết hơn với một tấn của các mẫu mã:

1

Một cách khác là xác định một MessageContract kiểu cho yêu cầu của bạn, cho phép bạn để xác định những gì hiển thị trong phần đầu và phần thân của thông điệp SOAP và điều chỉnh vùng tên được sử dụng. Ví dụ, hãy xem xét định nghĩa vụ sau đây:

[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; 
     } 
    } 

Gửi một yêu cầu tạo ra SOAP sau:

<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> 

Và câu trả lời từ các dịch vụ như sau:

<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>