2012-04-17 8 views
5

Buduję klienta do usługi STS i przez ponad jeden dzień próbuję dodać nagłówek do komunikatu WCF. W moim zaproszeniu do RequestSecurityToken muszę podać UsernameToken.Manipulowanie szczegółami nagłówka WCF

Nie jestem pewien, jak to osiągnąć. Na razie zdefiniowałem zachowanie punktu końcowego i inspektora wiadomości (zabrałem mnie wystarczająco długo, aby odkryć te ...). W BeforeSendRequest() tego ostatniego tworzę obiekt klasy niestandardowej "Security", która pochodzi od MessageHeader. Zabezpieczenia obejmują instancję 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(); 
} 

To, co jest w odcinkach

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

Zwłaszcza nazw z UsernameToken wydaje się być błędne. Wiem, że pochodzi z serializacji kontraktu danych, ale potrzebuję innej przestrzeni nazw.

To co chciałbym dane serializowane wyglądać

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

Czy moje podejście o prawo? I jak mogę manipulować takimi rzeczami, jak obszar nazw szczegółów nagłówka lub czy dane są serializowane jako atrybut lub element?

Aktualizacja


Ladislav Jak już wspomniano, nie mam do wdrożenia klasy jak UsernameToken siebie. Zrobiłem to tylko dlatego, że moja znajomość WCF jest tak ograniczona.

Do tej pory odkryłem, że WS2007HttpBinding, skonfigurowany do używania SecurityMode.TransportWithMessageCredential i z ustawieniem EstablishSecurityContext na false, daje prawie XML, którego szukam. Skąd mam wiedzieć?

Został jeszcze jeden problem: Moje żądanie zawiera pusty element body, w którym żądanie, które chcę utworzyć, zawiera element RequestSecurityToken wewnątrz elementu body. Czy ktoś wie, jak mogę to osiągnąć?

Użycie EstablishSecurityContext = true pomaga, ale jednocześnie zmienia moje działanie Soap z pożądanego "urn: RequestSecurityToken" na niepracujący "http://docs.oasis-open.org/ws-sx/ws -trust/200512/RST/SCT ".


Doceniam każdą odpowiedź!

Wielkie dzięki!

Björn

+1

http://stackoverflow.com/questions/5228430/how-to-add-attribute-to-wcf-message-header-with-messageheader-createheader-met Mam nadzieję, że to pomoże – v00d00

+3

Dlaczego robisz to ręcznie? Jeśli ustawisz konfigurację bezpieczeństwa WCF, doda te nagłówki. –

Odpowiedz

0

Istnieje kilka różnych sposobów, aby dodać nagłówki do wiadomości zależnie od tego, jak należy kontrolować zawartość nagłówka i gdzie trzeba wstawić nagłówek.

W kodzie aplikacji można utworzyć obiekt OperationContextScope wokół żądania, aby zmienić niektóre właściwości żądania. Wewnątrz OperationContextScope masz poprawną instancję OperationContext.Current, która umożliwia manipulowanie nagłówkami wiadomości za pośrednictwem kolekcji OutgoingMessageHeaders. Użycie tej metody głęboko upiecza kontrolę nagłówków w kodzie aplikacji. Musiałbyś być odpowiedzialny za skopiowanie odpowiedniego kodu wszędzie tam, gdzie był potrzebny.

Thesetwo linki (od kogoś z zespołu WCF) mówić o tym bardziej szczegółowo z ogromną ilością próbek kodu:

1

Jeden Alternatywnym sposobem jest zdefiniowanie MessageContract typ na żądanie, co pozwala aby określić, co pojawia się w nagłówku i treści komunikatu SOAP i dostosować wykorzystywany obszar nazw. Na przykład, rozważmy następującą definicję usługi:

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

Wysyłanie żądania produkuje następujące 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> 

a odpowiedź z usługi wygląda następująco:

<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> 
Powiązane problemy