2011-01-22 25 views
11

Necesito crear un servicio WCF alojado en IIS, utiliza el transporte http y el estado de espera en la memoria del servidor. Si bien soy consciente de que los servicios con estado no son una buena idea, esta última restricción es necesaria para que el servicio funcione con un cliente heredado.Sesiones WCF con un wsHttpBinding y sin seguridad de Windows

Lo primero que pensé fue en la sesión de asp.net para almacenar los valores. Activé el modo de compatibilidad asp.net en mi servicio, lo que me dio acceso al HttpContext, pero los valores que se colocaron en el objeto de sesión no se conservaban en la memoria. Supongo que esto se debió a que el módulo http que maneja el estado de la sesión no estaba configurado correctamente, pero cuando busqué la respuesta en Google, me encontré con las sesiones de WCF y pensé que podría ser una mejor idea usarlas.

Sin embargo, las sesiones de WCF parecen lo que sub-documentan y colocan un extraño conjunto de requisitos previos en un servicio, y no he podido encontrar una configuración que satisfaga mis necesidades: debe alojarse en IIS, debe usar http o El transporte de https no puede responder con la autenticación de Windows porque el cliente y el servidor no formarán parte del mismo dominio. Estoy tratando de hacer esto usando el wsHttpBinding, había escuchado que las sesiones de WCF requerían seguridad o mensaje confiable, pero: - Usando el enlace estándar y cuando los servidores no son parte del mismo dominio falla con una "SecurityNegotiationException The el llamante no fue autenticado por la excepción de servicio. Esto es bastante lógico ya que usaba la seguridad de Windows.

  • Si desactivo seguridad completa falla con un “Contrato requiere de sesión, pero la unión 'wsHttpBinding' no es compatible o no está configurado correctamente para apoyarlo.”

  • Si mientras se mantiene seguridad deshabilitada Habilito el mensaje confiable Obtengo la excepción "Falló la validación de enlace porque WSHttpBinding no admite sesiones confiables sobre seguridad de transporte (HTTPS). La fábrica de canales o el host de servicio no se pudieron abrir. Utilice seguridad de los mensajes para mensajería segura y fiable a través de HTTP “.

  • He intentado habilitar la seguridad de nivel de transporte, pero esto no parece hacer ninguna diferencia con el error generado

¿Hay alguna configuración que podría funcionar para mí? ¿O debería volver al plan de usar sesiones de asp.net?

+0

Encontró que la sesión de asp.net no funcionaba debido a que las cookies estaban deshabilitadas, tiene una versión funcional del código que usa sesiones asp.net. – Robert

Respuesta

25

Puede hacer que WCF mantenga la información de la sesión en la memoria de una manera bastante simple. Para eliminar cualquier posible influencia externa en mis instrucciones, supongo que está comenzando con un nuevo proyecto:

  1. Cree un nuevo proyecto de Biblioteca de servicios WCF. Este proyecto ya incluirá un servicio con un enlace WSHttpBiding preconfigurado.
  2. Ir al contrato de servicios (IService1.cs) y cambiar el atributo ServiceContract a lo siguiente:

    [ServiceContract(SessionMode = SessionMode.Required)] 
    
  3. Ir a la implimentation servicio (Service1.cs) y añadir el siguiente atributo ServiceBehavior al servicio clase (Service1):

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] 
    
  4. Agregar datos de la sesión como miembros de la clase de servicio (Service1):

    public class Service1 : IService1 
    { 
        ... 
    
        private string UserFullName { get; set; } 
    
        ... 
    } 
    
  5. Use los miembros para presentar los datos específicos de la sesión (recuerde también añadirlos al contrato de servicio, IService1):

    public class Service1 : IService1 
    { 
        ... 
    
        public string Welcome(string fullName) 
        { 
         UserFullName = fullName ?? "Guest"; 
         return string.Format("Welcome back, {0}!", UserFullName); 
        } 
    
        public string Goodbye() 
        { 
         return string.Format("Come back soon, {0}!", UserFullName ?? "Guest"); 
        } 
    
        ... 
    } 
    

SessionMode.Required asegura que sus clientes son sesión de seguimiento.
InstanceContextMode.PerSession asegura que se crea una instancia de su clase de servicio (Service1) para cada sesión, de modo que puede retener datos de sesión en ella y existirá en la memoria en varias llamadas en la misma sesión.
ConcurrencyMode.Single asegura que solo un subproceso puede entrar en cada instancia de clase de servicio (Servicio1) y evita posibles problemas de concurrencia si solo accede a datos de la clase de servicio (y ubicaciones externas seguras para subprocesos).

EDITAR: De forma predeterminada, WSHttpBinding solo permite sesiones de seguridad. Pero también admite sesiones fiables, que permiten establecer sesiones sin seguridad habilitada. La siguiente configuración de enlace desactiva la seguridad y habilita sesiones confiables:

<wsHttpBinding> 
    <binding name="wsHttpBindingConfiguration"> 
     <security mode="None" /> 
     <reliableSession enabled="true" /> 
    </binding> 
</wsHttpBinding> 
+0

Esto es más o menos lo que hice, parece que necesita autenticación de Windows a nivel de mensaje para funcionar. Esta no es una opción para mí, ya que el cliente y el servidor no estarán en el mismo dominio. – Robert

+0

@Robert: correcto, pero hay una solución. Ver la edición en mi respuesta. Espero que esto resuelva tu problema. –

+0

Al usar la configuración sugerida en el cliente, aparece el siguiente error. ProtocolException: el extremo remoto ha enviado un error no reconocido con el espacio de nombre, http://www.w3.org/2003/05/soap-envelope, el nombre del remitente y el motivo El mensaje no se pudo procesar. Esto es muy probable porque la acción 'http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence' es incorrecta o porque el mensaje contiene un token de contexto de seguridad no válido o caducado o porque hay .. – Robert

1

IMO esto es lo que sucede cuando se utiliza una tecnología con una abstracción pobre sobre HTTP como WCF. El hecho de que los servicios web de WCF en teoría podrían alojarse sin HTTP (es decir, a través de TCP NET, MSMQ, etc.) simplemente dificulta el uso de funciones incorporadas de HTTP sin entrar en el infierno de la configuración y comenzar un juego de "adivinar la configuración correcta" por prueba y error "donde prueba todas las configuraciones posibles de permutación hasta que encuentre la correcta que funcione!

En última instancia, si no podía usar WCF y tenía que implementar el servicio web desde cero, simplemente establecería una cookie cuando el cliente se autenticara correctamente. Luego, con cada solicitud del cliente, simplemente tome la información de sesión a la que hace referencia esa cookie.

Una solución posible si se tenía que utilizar WCF es tomar la gestión de sesiones en sus propias manos (Es lo que hago cuando estoy satisfecho con el esfuerzo necesario para que algo funcione) y tienen un explícito 'Sesión 'propiedad en todos sus servicios web que requieren una sesión/autenticación (generalmente un guid generado en la Autenticación). Entonces, para cada solicitud posterior, utiliza el guid para rehidratar la información de sesión asociada con ese cliente.

Si está interesado en probar diferentes frameworks de servicios web, tengo un Open Source Web Services Framework que le permite crear servicios web sin configuración, DRY y comprobables donde (sin ninguna configuración requerida) cada servicio web que crea es automáticamente accesible a través de REST Puntos finales XML, JSON, JSV, SOAP 1.1, SOAP 1.2. Efectivamente, le permite acceder a su mismo servicio web a través de una url HTTP GET para clientes REST-ful y fácil depuración, así como puntos finales SOAP (una opción popular que todavía imponen algunas empresas). El tutorial Hello World debería darle una buena visión general de algunas de sus características y cómo funciona.

+0

¡Gracias por la respuesta! Aunque estoy de acuerdo en gran medida con su respuesta, es una limitación desafortunada del proyecto que tengamos que usar WCF. Definitivamente echaré un vistazo a ServiceStack para proyectos con restricciones menos estrictas sobre las tecnologías que se utilizarán. – Robert

Cuestiones relacionadas