Sessioni WCF con un wsHttpBinding e senza la sicurezza di Windows

Devo creare un servizio WCF ospitato in IIS, utilizza il trasporto HTTP e lo stato di attesa nella memoria del server. Mentre sono consapevole che i servizi di stato non sono una buona idea, questo ultimo vincolo è necessario per far funzionare il servizio con un client legacy.

Il mio primo pensiero è stato la sessione di asp.net per memorizzare i valori. Ho triggersto la modalità di compatibilità asp.net nel mio servizio, che mi ha dato l’accesso a HttpContext, ma i valori che erano stati inseriti nell’object di sessione non venivano mantenuti in memoria. Presumo che questo fosse dovuto al fatto che il modulo http che gestiva lo stato della sessione non era configurato correttamente, ma quando cercavo su Google mi sono imbattuto in sessioni di WCF e pensavo che sarebbe stata una buona idea utilizzarle.

Tuttavia, le sessioni di WCF sembrano ciò che è sottocosto e collocano uno strano insieme di prerequisiti su un servizio, e non sono stato in grado di trovare una configurazione che si adatta alle mie esigenze: deve essere ospitato in IIS, deve utilizzare il trasporto http o https e può rispondere all’autenticazione di Windows perché il client e il server non faranno parte dello stesso dominio. Sto cercando di ottenere questo usando wsHttpBinding, ho sentito che le sessioni di WCF richiedevano un messaggio di sicurezza o affidabile, ma: – Usando l’associazione standard e quando i server non fanno parte dello stesso dominio fallisce con un “SecurityNegotiationException Il chiamante non è stato autenticato dal servizio “eccezione. Questo è abbastanza logico in quanto utilizzava la sicurezza di Windows.

  • Se disattivo la sicurezza completa fallisce con un “Contratto richiede Session, ma Binding ‘WSHttpBinding’ non lo supporta o non è configurato correttamente per supportarlo.”

  • Se mantenendo la sicurezza disabilitata, abilito il messaggio affidabile, ottengo l’eccezione “Convalida del bind non riuscita perché WSHttpBinding non supporta sessioni affidabili sulla sicurezza del trasporto (HTTPS). Non è stato ansible aprire la factory del canale o l’host del servizio. Usa la sicurezza dei messaggi per la messaggistica sicura sicura su HTTP. ”

  • Ho provato ad abilitare la sicurezza del livello di trasporto, ma questo non sembra fare alcuna differenza per l’errore generato

C’è qualche configurazione che potrebbe funzionare per me? O dovrei semplicemente tornare al piano di usare le sessioni di asp.net?

È ansible avere le informazioni sulla sessione di attesa WCF in memoria in un modo piuttosto semplice. Per eliminare eventuali influenze esterne nelle mie istruzioni, presumo che tu stia iniziando con un nuovo progetto:

  1. Creare un nuovo progetto della libreria di servizi WCF. Questo progetto conterrà già un servizio con un binding WSHttpBiding preconfigurato.
  2. Vai al contratto di servizio (IService1.cs) e modifica l’attributo ServiceContract al seguente:

     [ServiceContract(SessionMode = SessionMode.Required)] 
  3. Passare al servizio di installazione (Service1.cs) e aggiungere il seguente attributo ServiceBehavior alla class di servizio ( Service1 ):

     [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)] 
  4. Aggiungi dati di sessione come membri della class di servizio ( Service1 ):

     public class Service1 : IService1 { ... private string UserFullName { get; set; } ... } 
  5. Utilizzare i membri per presentare dati specifici della sessione (ricordarsi di aggiungerli anche al contratto di servizio, 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 garantisce che i tuoi clienti siano tracciati sulla sessione.
InstanceContextMode.PerSession assicura che venga creata un’istanza della class di servizio (Service1) per ogni sessione, in modo che sia ansible conservare i dati di sessione al suo interno e che esisterà in memoria attraverso più chiamate nella stessa sessione.
ConcurrencyMode.Single garantisce che solo un thread possa immettere ciascuna istanza della class di servizio (Service1) e impedisce possibili problemi di concorrenza se si accede solo ai dati dalla class di servizio (e alle posizioni esterne thread-safe).

MODIFICA: per impostazione predefinita, WSHttpBinding consente solo sessioni di sicurezza. Ma supporta anche sessioni affidabili, che consentono di stabilire sessioni senza la sicurezza abilitata. La seguente configurazione vincolante disabilita la sicurezza e abilita sessioni affidabili:

       

IMO questo è ciò che accade quando usi una tecnologia con una scarsa astrazione su HTTP come WCF. Il fatto che i servizi Web WCF possano in teoria essere ospitati senza HTTP (cioè su NET TCP, MSMQ, ecc.) Rende difficile l’uso delle funzionalità integrate di HTTP senza entrare nella configurazione dell’inferno e avviare un gioco di “indovinare la configurazione corretta per tentativi ed errori “dove provi ogni ansible permutazione di configurazione finché non trovi quella giusta che funziona!

In definitiva, se non si potesse usare WCF e si dovesse implementare il servizio Web da zero, si sarebbe semplicemente impostato un cookie quando il client si fosse autenticato con successo. Quindi, con ogni richiesta del cliente, acquisisci le informazioni sulla sessione a cui fa riferimento quel cookie.

Una ansible soluzione se devi utilizzare WCF è prendere la gestione delle sessioni nelle tue mani (è quello che faccio quando non sono soddisfatto dello sforzo richiesto per far funzionare qualcosa) e avere una proprietà esplicita di “Session” su tutto il tuo web servizi che richiedono una sessione / autenticazione (di solito un guid generato in Autenticazione). Quindi per ogni richiesta successiva si utilizza il guid per reidratare le informazioni sulla sessione associate a quel client.

Se sei interessato a provare diversi framework di servizi web, mantengo un framework di servizi Web open source che ti consente di creare servizi web privi di configurazione, DRY e testabili dove (senza alcuna configurazione richiesta) ogni servizio web che crei è automaticamente accessibile su REST XML, JSON, JSV, SOAP 1.1, SOAP 1.2 endpoint. Effettivamente consente di accedere al tuo stesso servizio web tramite un URL GET HTTP per client REST-ful e debug facile così come endpoint SOAP (una scelta popolare ancora richiesta da alcune aziende). Il tutorial Hello World dovrebbe darti una buona panoramica su alcune delle sue funzioni e su come funziona.