Catch-22 evita el servicio TCP WCF transmitido asegurable por WIF; arruinando mi navidad, salud mental


181

Tengo un requisito para asegurar un punto final del servicio WCF net.tcp con WIF . Debe autenticar las llamadas entrantes en nuestro servidor de tokens. El servicio se transmite porque está diseñado para transferir grandes cantidades de datos y cosas.

Esto parece ser imposible. Y si no puedo evitar las capturas, mi Navidad se arruinará y moriré de un trago mientras los felices compradores pasan por encima de mi cuerpo que se enfría lentamente. Totalmente en serio, chicos.

¿Por qué es esto imposible? Aquí está el Catch-22.

En el cliente, necesito crear un canal con GenericXmlSecurityToken que obtengo de nuestro servidor de tokens. No hay problema.

// people around here hate the Framework Design Guidelines.
var token = Authentication.Current._Token;
var service = base.ChannelFactory.CreateChannelWithIssuedToken(token);
return service.Derp();

¿Dije "no problemo"? Problemo De hecho, el NullReferenceExceptionestilo de problema.

"Hermano", le pregunté al Marco, "¿ni siquiera tienes cheque nulo?" El Marco estaba en silencio, así que lo desarme y descubrí que

((IChannel)(object)tChannel).
    GetProperty<ChannelParameterCollection>().
    Add(federatedClientCredentialsParameter);

fue la fuente de la excepción, y que la GetPropertyllamada estaba regresando null. Entonces, ¿WTF? Resulta que si enciendo la seguridad del Mensaje y configuro el tipo de credencial del cliente IssuedToken, esta propiedad ahora existe en ClientFactory(protip: No hay un equivalente de "SetProperty" en IChannel, el bastardo).

<binding name="OMGWTFLOL22" transferMode="Streamed" >
    <security mode="Message">
        <message clientCredentialType="IssuedToken"/>
    </security>
</binding>

Dulce. No más NRE. Sin embargo, ahora mi cliente tiene una falla al nacer (todavía lo amo, aunque). Excavando los diagnósticos de WCF (resumen: haz que tus peores enemigos hagan esto después de aplastarlos y conducirlos ante ti, pero justo antes de disfrutar de las lamentaciones de sus mujeres y niños), veo que es debido a una falta de coincidencia de seguridad entre el servidor y el cliente.

La actualización solicitada no es compatible con 'net.tcp: // localhost: 49627 / MyService'. Esto podría deberse a enlaces no coincidentes (por ejemplo, seguridad habilitada en el cliente y no en el servidor).

Verificando los diags del host (de nuevo: aplastar, conducir, leer registros, disfrutar lamentaciones), veo que esto es cierto

El tipo de protocolo application / ssl-tls se envió a un servicio que no admite ese tipo de actualización.

"Bueno, yo mismo", le digo, "¡Solo activaré la seguridad de mensajes en el host!" Y yo si. Si desea saber cómo se ve, es una copia exacta de la configuración del cliente. Buscar.

Resultado: Kaboom.

El enlace ('NetTcpBinding', ' http://tempuri.org/ ') admite la transmisión que no se puede configurar junto con la seguridad a nivel de mensaje. Considere elegir un modo de transferencia diferente o elegir el nivel de seguridad de transporte.

Por lo tanto, mi host no se puede transmitir y proteger a través de tokens . 22 capturas.

tl; dr: ¿Cómo puedo asegurar un punto final net.tcp WCF transmitido mediante WIF?


3
Ok, probablemente una pregunta ignorante aquí, pero ¿WIF realmente requiere el modo Mensaje? Parece que el modo de transporte funcionaría mejor con la transmisión, algo como lo que obviamente no se ha probado<security mode="Transport" /> <transport clientCredentialType="IssuedToken" /> </security>
Joachim Isaksson

3
TransportWithMessageCredentialEl modo puede ser otra opción.
Joachim Isaksson

3
TMLK, MessageSecurity puede firmar y cifrar la carga útil almacenada en el búfer, pero no funciona cuando se trata de transmisiones. ¿Has pensado en usar auditMode = IssuedTokenOverTransport?
OnoSendai

77
Déjame ver si puedo convocar a algunos fantasmas del pasado para ayudar a salvar tus vacaciones. Algunos consejos aquí: social.msdn.microsoft.com/Forums/vstudio/en-US/…
OnoSendai

2
¿Hay alguna posibilidad de que pueda publicar un proyecto de caso de prueba con el que otros puedan experimentar?
antiduh

Respuestas:


41

WCF tiene problemas en algunas áreas con la transmisión (lo estoy mirando, MTOM 1 ) debido a un problema fundamental en la forma en que no realiza la autenticación previa de la manera en que la mayoría de la gente pensaría que debería funcionar (solo afecta las solicitudes posteriores para ese canal , no es la primera solicitud) Ok, entonces este no es exactamente tu problema, pero síguelo ya que llegaré al tuyo al final. Normalmente, el desafío HTTP funciona así:

  1. el cliente accede al servidor de forma anónima
  2. el servidor dice, lo siento, 401, necesito autenticación
  3. el cliente accede al servidor con token de autenticación
  4. El servidor acepta.

Ahora, si alguna vez intenta habilitar la transmisión MTOM en un punto final WCF en el servidor, no se quejará. Pero, cuando lo configura en el proxy del cliente (como debe hacerlo, deben coincidir con los enlaces) explotará en una muerte ardiente. La razón de esto es que la secuencia de eventos anterior que WCF está tratando de prevenir es la siguiente:

  1. el cliente transmite el archivo de 100 MB al servidor de forma anónima en una sola POST
  2. el servidor dice que lo siento, 401, necesito autenticación
  3. el cliente vuelve a transmitir un archivo de 100 MB al servidor con un encabezado de autenticación
  4. El servidor acepta.

Tenga en cuenta que acaba de enviar 200 MB al servidor cuando solo necesitaba enviar 100 MB. Bueno, este es el problema. La respuesta es enviar la autenticación en el primer intento, pero esto no es posible en WCF sin escribir un comportamiento personalizado. De todos modos, estoy divagando.

Tu problema

Primero, déjame decirte que lo que estás intentando es imposible 2 . Ahora, para que dejes de girar tus ruedas, déjame decirte por qué:

Me parece que ahora estás vagando en una clase de problema similar. Si habilita la seguridad a nivel de mensaje, el cliente debe cargar todo el flujo de datos en la memoria antes de que pueda cerrar el mensaje con la función hash habitual y la firma xml requerida por ws-security. Si tiene que leer la transmisión completa para firmar el mensaje único (que no es realmente un mensaje, pero es una transmisión continua única), puede ver el problema aquí. WCF tendrá que transmitirlo una vez "localmente" para calcular la seguridad del mensaje, luego transmitirlo nuevamente para enviarlo al servidor. Esto es claramente una tontería, por lo que WCF no permite la seguridad a nivel de mensaje para la transmisión de datos.

Entonces, la respuesta simple aquí es que debe enviar el token como un parámetro al servicio web inicial o como un encabezado SOAP y usar un comportamiento personalizado para validarlo. No puede usar WS-Security para hacer esto. Francamente, esto no es solo un problema de WCF: no puedo ver cómo podría funcionar prácticamente para cualquier otra pila.

Resolviendo el problema MTOM

Esto es solo un ejemplo de cómo resolví mi problema de transmisión de MTOM para la autenticación básica, por lo que tal vez podría tomar las agallas de esto e implementar algo similar para su problema. El quid de la cuestión es que para habilitar su inspector de mensajes personalizado, debe deshabilitar toda noción de seguridad en el proxy del cliente (permanece habilitado en el servidor), aparte del nivel de transporte (SSL):

this._contentService.Endpoint.Behaviors.Add(
    new BasicAuthenticationBehavior(
        username: this.Settings.HttpUser,
        password: this.Settings.HttpPass));
var binding = (BasicHttpBinding)this._contentService.Endpoint.Binding;
binding.Security.Mode = BasicHttpSecurityMode.Transport; // SSL only            
binding.Security.Transport.ClientCredentialType = 
   HttpClientCredentialType.None; // Do not provide

Tenga en cuenta que he desactivado la seguridad del transporte aquí porque lo proporcionaré yo mismo utilizando un inspector de mensajes y un comportamiento personalizado:

internal class BasicAuthenticationBehavior : IEndpointBehavior
{
    private readonly string _username;
    private readonly string _password;

    public BasicAuthenticationBehavior(string username, string password)
    {
        this._username = username;
        this._password = password;
    }
    public void AddBindingParameters(ServiceEndpoint endpoint, 
        BindingParameterCollection bindingParameters) { }
    public void ApplyClientBehavior(ServiceEndpoint endpoint,
        ClientRuntime clientRuntime)
    {
        var inspector = new BasicAuthenticationInspector(
            this._username, this._password);
        clientRuntime.MessageInspectors.Add(inspector);
    }
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
        EndpointDispatcher endpointDispatcher) { }
    public void Validate(ServiceEndpoint endpoint) { }
}

internal class BasicAuthenticationInspector : IClientMessageInspector
{
    private readonly string _username;
    private readonly string _password;

    public BasicAuthenticationInspector(string username, string password)
    {
        this._username = username;
        this._password = password;
    }

    public void AfterReceiveReply(ref Message reply,
        object correlationState) { }

    public object BeforeSendRequest(ref Message request,
        IClientChannel channel)
    {
        // we add the headers manually rather than using credentials 
        // due to proxying issues, and with the 101-continue http verb 
        var authInfo = Convert.ToBase64String(
            Encoding.Default.GetBytes(this._username + ":" + this._password));

        var messageProperty = new HttpRequestMessageProperty();
        messageProperty.Headers.Add("Authorization", "Basic " + authInfo);
        request.Properties[HttpRequestMessageProperty.Name] = messageProperty;

        return null;
    }
}

Por lo tanto, este ejemplo es para cualquier persona que esté sufriendo el problema MTOM, pero también como un esqueleto para que implemente algo similar para autenticar su token generado por el servicio de token protegido por WIF primario.

Espero que esto ayude.

(1) Grandes datos y transmisión

(2) Seguridad de mensajes en WCF (ver "desventajas")


MTOM and Basic Authorizationy MTOM y OAuth2 ?
Kiquenet
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.