2012-04-17 13 views
5

Estoy creando un cliente para algún servicio de STS y por más de un día estoy intentando agregar un encabezado a un mensaje de WCF. En mi llamada a RequestSecurityToken, tengo que incluir un UsernameToken.Manipulación de los detalles del encabezado de WCF

No estoy seguro de cómo lograr eso. Por el momento, definí un comportamiento de punto final y un inspector de mensajes (me tomó el tiempo suficiente para descubrir esos ...). En BeforeSendRequest() de este último creo un objeto de la clase personalizada 'Security' que deriva de MessageHeader. La seguridad incluye una instancia de 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(); 
} 

Esto es lo que se publica por entregas

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

Especialmente el espacio de nombres de UsernameToken parece estar mal. Sé que proviene de la serialización del contrato de datos, pero necesito un espacio de nombres diferente.

Esto es lo que me gustaría que los datos serializados para que parezca

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

¿Es mi enfoque sobre la derecha? ¿Y cómo puedo manipular cosas como el espacio de nombres de un detalle de encabezado o si los datos se serializan como atributo o elemento?

actualización


Como ya se ha señalado Ladislav, no tengo para implementar clases como UsernameToken mí mismo. Lo hice solo porque mi conocimiento de WCF es muy limitado.

Por ahora, descubrí que WS2007HttpBinding, configurado para usar SecurityMode.TransportWithMessageCredential y con EstablishSecurityContext establecido en false produce casi el XML que estoy buscando. ¿Cómo debería haberlo sabido?

Pero queda un problema: Mi solicitud tiene un elemento de cuerpo vacío, donde la solicitud que quiero producir, presenta un elemento RequestSecurityToken dentro del elemento de cuerpo. ¿Alguien sabe cómo puedo lograr eso?

El uso de EstablishSecurityContext = true ayuda, pero al mismo tiempo, cambia mi Soap-Action de la "urna deseada: RequestSecurityToken" en el no funcional "http://docs.oasis-open.org/ws-sx/ws -trust/200512/RST/SCT ".


¡Agradezco la respuesta!

¡Muchas gracias!

Björn

+1

http://stackoverflow.com/questions/5228430/how-to-add-attribute-to-wcf-message-header-with-messageheader-createheader-met Espero que esto ayude – v00d00

+3

¿Por qué lo haces manualmente? Si configura la configuración de seguridad de WCF, agregará esos encabezados por usted. –

Respuesta

0

Hay algunas maneras diferentes de agregar encabezados de un mensaje dependiendo de lo que necesita para controlar el contenido de la cabecera y donde es necesario insertar la cabecera.

En el código de su aplicación puede crear un OperationContextScope alrededor de la solicitud para cambiar algunas de las propiedades de la solicitud. Dentro de un OperationContextScope, tiene una instancia válida de OperationContext.Current, que permite la manipulación de los encabezados de los mensajes a través de la colección OutgoingMessageHeaders. El uso de este método agota profundamente el control de los encabezados en el código de la aplicación. Debería ser responsable de copiar el código apropiado donde sea que se necesite.

Thesetwo enlaces (de alguien en el equipo WCF) hablan de esto en mayor detalle con un montón de ejemplos de código:

1

Una forma alternativa es definir un MessageContract tipo para su solicitud, que le permite para definir lo que aparece en el encabezado y el cuerpo del mensaje SOAP y ajustar el espacio de nombres utilizado. Por ejemplo, considere la siguiente definición de servicio:

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

Enviar una solicitud produce el siguiente 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> 

Y una respuesta del servicio se ve así:

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