2010-08-23 26 views
6

Tôi đang gọi một dịch vụ không phải WCF từ máy khách WCF. Ứng dụng khách WCF bao gồm thuộc tính tiêu đề "MustUnderstand" được đặt thành "1". Dưới đây là một yêu cầu SOAP tiêu biểu:Cách sửa đổi MustUnderstand của tiêu đề thư của WCF bằng ClientInspector

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 
<s:Header> 
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
     <u:Timestamp u:Id="_0"> 
      <u:Created>2010-08-23T20:48:52.680Z</u:Created> 
      <u:Expires>2010-08-23T20:53:52.680Z</u:Expires> 
     </u:Timestamp> 
     <o:UsernameToken u:Id="uuid-72ea0c0a-43aa-43b2-bed7-c2da13624105-1"> 
      <o:Username>blablabla</o:Username> 
      <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">blablabla</o:Password> 
     </o:UsernameToken> 
    </o:Security> 
</s:Header> 
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <HeartbeatRequest xmlns="http://removed"> 
     <DateTime xmlns="">8/23/2010 4:48:51 PM</DateTime> 
     <Message xmlns="">123</Message> 
    </HeartbeatRequest> 
</s:Body> 

Bây giờ, đây là câu trả lời tôi nhận được lại cho việc này.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<soapenv:Header> 
    <Misunderstood qname="o:Security" xmlns="http://www.w3.org/2002/06/soap-faults" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" /> 
</soapenv:Header> 
<soapenv:Body> 
    <soapenv:Fault xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
     <faultcode>soapenv:MustUnderstand</faultcode> 
     <faultstring>WSWS3173E: Error: Did not understand &quot;MustUnderstand&quot; header(s):{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security</faultstring> 
    </soapenv:Fault> 
</soapenv:Body> 

Lưu ý phần về MustUnderstand không được hiểu.

Chủ sở hữu dịch vụ này đã cho biết rằng họ cho phép các phần tử có tiền tố không gian tên WSSE nhưng không thực sự trong XSD và thực hiện một số quá trình xử lý khác để ngăn chúng chấp nhận MustUnderstand = "1", vì vậy tôi phải tìm cách gửi tin nhắn bằng MustUnderstand = "0".

Tôi đã cố gắng thay đổi điều này trong MessageContract cho ứng dụng khách proxy bằng cách sử dụng thuộc tính MessageHeader, nhưng điều đó không giúp ích gì.

Tiếp theo, tôi đã triển khai trình kiểm tra thư khách hàng tùy chỉnh. Tôi tạo ra các lớp học mỗi MSDN cho một hành vi tùy chỉnh mở rộng phần tử và một IEndpointBehavior, đây là tầm thường nhưng ở đây cho đầy đủ:

public class ExClientBehavior : IEndpointBehavior 
{ 
    #region IEndpointBehavior Members 

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { 
     // no op 
    } 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
     ExInspector inspector = new ExInspector(); 
     clientRuntime.MessageInspectors.Add(inspector); 
    } 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
    { 
     // no op 
    } 

    public void Validate(ServiceEndpoint endpoint) 
    { 
     // no op 
    } 

    #endregion 
} 


    public class ExClientBehaviorExtensionElement : BehaviorExtensionElement 
{ 
    public override Type BehaviorType 
    { 
     get { return typeof(ExClientBehavior); } 
    } 

    protected override object CreateBehavior() 
    { 
     return new ExClientBehavior(); 
    } 
} 

và bây giờ thanh tra thực tế:

public class ExInspector : IClientMessageInspector 
{ 

    #region IClientMessageInspector Members 

    public void AfterReceiveReply(ref Message reply, object correlationState) 
    { 
     // no op 
     return; 
    } 

    public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
     MessageBuffer buffer = request.CreateBufferedCopy(int.MaxValue); 

     Message newMessage = buffer.CreateMessage(); 

     newMessage.Headers.RemoveAt(0); 

     newMessage.Headers.Add(MessageHeader.CreateHeader 
      (
       request.Headers[0].Name, 
       request.Headers[0].Namespace, 
       string.Empty, 
       false, 
       string.Empty, 
       request.Headers[0].Relay 
      ) 
     ); 

     request = newMessage; 

     return null; 
    } 

    #endregion 
} 

Như bạn thấy đấy, tôi đang tạo ra một yêu cầu mới thông qua bản sao đệm, sau đó xóa tiêu đề bảo mật (chỉ có một tiêu đề) và thêm một tiêu đề mới với MustUnderstand được đặt thành false (tại sao tôi làm điều này? MessageHeader.MustUnderstand là chỉ đọc). Tôi đặt một điểm ngắt trong phương thức này và thực sự, tiêu đề mới được thêm vào, newMessage được viết lại theo yêu cầu và cả newMessage.Headers [0] .MustUnderstand cũng như request.Headers [0] .MustUnderstand là false tại kết thúc của phương pháp này.

Tuy nhiên, thư được gửi tới dịch vụ vẫn bao gồm MustUnderstand = "1" trên tiêu đề !!!!!

Đây là app.config trong đó bao gồm các hành vi trên:

<configuration> 
<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
      <binding name="WebServiceSOAP" closeTimeout="00:01:00" openTimeout="00:01:00" 
        receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" 
        bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
        maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 
        messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
        useDefaultWebProxy="true"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
       <security mode="TransportWithMessageCredential"> 
        <transport clientCredentialType="Basic" proxyCredentialType="None" realm="" /> 
        <message clientCredentialType="UserName" algorithmSuite="Default" /> 
       </security> 
      </binding> 
     </basicHttpBinding> 
    </bindings> 
    <client> 
     <endpoint 
       address="https://removed" 
       behaviorConfiguration="ovrExClientBehavior" 
       binding="basicHttpBinding" 
       bindingConfiguration="WebServiceSOAP" 
       contract="EWebService.EWebService" 
       name="WebServiceSOAP" /> 
    </client> 
    <extensions> 
     <behaviorExtensions> 
      <add name="exClientBehavior" type="ExMessageInspector.ExClientBehaviorExtensionElement, ExMessageInspector, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> 
     </behaviorExtensions> 
    </extensions> 
    <behaviors> 
     <endpointBehaviors> 
      <behavior name="ovrExClientBehavior"> 
       <exClientBehavior /> 
      </behavior> 
     </endpointBehaviors> 
    </behaviors> 
</system.serviceModel> 

Vì vậy, câu hỏi của tôi: là nó có thể thay đổi MustUnderstand trên một thông báo đi như trên, hoặc theo cách tương tự? Hoặc là nó buộc phải được thay đổi trở lại sự thật sau này trong đường ống, sau khi thanh tra thay thế tiêu đề bảo mật? Lưu ý: chủ sở hữu dịch vụ nói rằng họ chỉ biết một tổ chức khác đang sử dụng dịch vụ này trong .NET. Và người tiêu dùng đó về cơ bản phải loại bỏ WCF và WSE và tạo các thông điệp SOAP - và xử lý các câu trả lời - từ đầu , có thể sử dụng POX POST hoặc một số ứng dụng như vậy. Chúng tôi thực sự muốn tránh điều này vì chúng tôi cần gọi một số hoạt động trên dịch vụ.

Ngoài ra, chúng tôi cần phải giữ nguyên phần thân và thuộc tính của thông báo.

Mọi trợ giúp sẽ thực sự được đánh giá cao !!

Trả lời

5

Tôi tự hỏi tại sao các tiêu chuẩn về khả năng tương tác tồn tại nếu các nhà cung cấp không tuân theo chúng. Nếu trình kiểm tra khách hàng không hoạt động, bạn có thể thử triển khai bộ mã hóa thông điệp tùy chỉnh và sửa đổi tiêu đề ở đó.

Edit:

Câu hỏi đặt ra ở đây là tại sao bạn gửi thông tin người dùng để xác thực nếu bạn trong cùng một thời tuyên bố dịch vụ mà không cần phải hiểu được những tiêu đề với chứng chỉ = không nhất thiết phải sử dụng chúng. Bạn có thực sự cần chúng?

Có các cách tiếp cận khác phụ thuộc vào yêu cầu của bạn. Bạn có cần dấu thời gian không? Dấu thời gian có được kiểm tra trên máy chủ không? Bạn có người dùng duy nhất cho tất cả các cuộc gọi hoặc bạn có phải là người dùng khác nhau giữa các cuộc gọi không?

Nếu bạn không cần dấu thời gian hoặc dấu thời gian không được chọn và bạn chỉ có một tên người dùng và mật khẩu, cách dễ nhất là không sử dụng chế độ bảo mật TranportWithMessageCredential. Sử dụng Giao thông vận tải tinh khiết để thay thế và vị trí mô tả tiêu đề bên trong cấu hình thiết bị đầu cuối của khách hàng như:

<client> 
    <endpoint address="https://removed" binding="basicHttpBinding" bindingConfiguration="WebServiceSOPA" contract="EWebService.EWebService" name="WebServiceSOAP"> 
    <headers> 
    <wsse:Security s:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
     <wsse:UsernameToken wsu:Id="SecurityToken-3f7f983f-66ce-480d-bce6-170632d33f92" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 
     <wsse:Username>User</wsse:Username> 
     <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Pwd123</wsse:Password> 
     </wsse:UsernameToken> 
    </wsse:Security> 
    </headers> 
    </endpoint> 
    </client> 

Nếu bạn có một vài tên người dùng hoặc nếu bạn cần timestamp thực với dữ liệu thực tế bạn có thể sử dụng phương pháp tương tự nhưng thay vì cấu hình tĩnh bạn có thể tạo tùy chỉnh tiêu đề trong mã và tránh bảo mật WCF. Điều này có thể được thực hiện bằng cách sử dụng thanh tra thư.

+0

Thật không may, nhà cung cấp này kết hợp MustUnderstand = 0 với việc vẫn đang ủy thác tên người dùng/mật khẩu (tĩnh) trong tiêu đề. Nếu chúng tôi bỏ qua điều đó, chúng tôi sẽ trả về lỗi diễn viên bị thiếu (tức là thiếu phần tử). Tôi không nghĩ rằng dấu thời gian là bắt buộc. Hm - Tôi sẽ thử phương pháp cấu hình điểm cuối và nhận xét lại. – pelazem

+0

OK, cảm ơn Ladislav! Tôi đã thử cách tiếp cận của bạn, và vì chúng tôi "may mắn" đủ để có một tên người dùng/mật khẩu tĩnh, đi với Transport chỉ để bảo mật và tiêu đề tĩnh khi bạn đặt nó ra - hoạt động !! Cảm ơn nhiều. – pelazem

+0

Ladislav, cảm ơn vì cách tiếp cận, nhưng tôi không thể sử dụng nó. Khi tôi đã thêm tiêu đề này vào cấu hình điểm cuối, tôi đã có lỗi biên dịch 's: tiền tố không được định nghĩa'. Bạn có thể vui lòng đưa ra nhận xét về không gian tên cần được sử dụng trong tiêu đề này không. –

Các vấn đề liên quan