2009-05-26 4 views
6

Tutti,non valido o scaduto token di contesto di sicurezza nel servizio Web WCF

Ho un servizio WCF web (diamo servizio chiamato "B") ospitato in IIS utilizzando un account di servizio (VM, Windows 2003 SP2). Il servizio espone un endpoint che utilizza WSHttpBinding con i valori predefiniti tranne per maxReceivedMessageSize, maxBufferPoolSize, maxBufferSize e alcuni dei timeout che sono stati aumentati.

Il servizio Web è stato sottoposto a test di carico utilizzando il framework di prova del carico di Visual Studio con circa 800 utenti simultanei e ha superato tutti i test senza eccezioni. Il proxy nel test di unità è stato creato dalla configurazione.

Esiste un'applicazione di condivisione che utilizza il servizio di ricerca di Office Sharepoint Server per chiamare i servizi Web "A" e "B". L'applicazione riceverà i dati dal servizio "A" per creare una richiesta che verrà inviata al servizio "B". La risposta proveniente dal servizio "B" è indicizzata per la ricerca. Il proxy viene creato a livello di programmazione utilizzando ChannelFactory.

Quando il servizio "A" richiede meno di 10 minuti, le chiamate al servizio "B" hanno esito positivo. Ma quando il servizio "A" richiede più tempo (~ 20 minuti) le chiamate al servizio "B" generano la seguente eccezione:

Messaggio di eccezione: un errore non protetto o errato è stato ricevuto dall'altra parte. Vedere la FaultException interna per il codice di errore e il dettaglio Messaggio di eccezione interna: il messaggio non può essere elaborato. Ciò è probabilmente dovuto al fatto che l'azione 'namespace/OperationName' non è corretta o perché il messaggio contiene un token di contesto di sicurezza non valido o scaduto o perché c'è una mancata corrispondenza tra i binding. Il token del contesto di sicurezza non sarebbe valido se il servizio interrompesse il canale a causa di inattività. Per evitare che il servizio interrompa anticipatamente le sessioni inattive, aumentare il timeout di ricezione sull'associazione dell'endpoint del servizio.

Le impostazioni di associazione sono uguali, l'ora in entrambi server client e server di servizi Web si sincronizzano con il servizio Ora di Windows, stesso fuso orario.

quando guardo il server dove il servizio web "B" è ospitato, posso vedere gli errori seguenti di sicurezza in fase di ingresso:

Fonte: Sicurezza

Categoria: Accesso/fine sessione

ID evento : 537

utente NT AUTHORITY \ SYSTEM

Errore di accesso:

Motivo: Si è verificato un errore durante l'accesso

Tipo di accesso: 3

Processo di accesso: Kerberos

Pacchetto di autenticazione: Kerberos

Codice di stato: 0xC000006D

codice di stato secondario: 0xC0000133

Dopo aver letto alcuni dei blog online, la Sta codice tus significa STATUS_LOGON_FAILURE e il codice del sottostato indica STATUS_TIME_DIFFERENCE_AT_DC. ma ho già controllato entrambi gli orologi server e client e sono sincronizzati.

Ho anche notato che il token di sicurezza sembra essere memorizzato nella cache da qualche parte nel server client perché ha un altro processo che chiama il servizio web "B" utilizzando lo stesso account di servizio e ottiene i dati con successo per la prima volta. Quindi, avvia il processo per aggiornare gli indici del servizio di ricerca del server sharepoint dell'ufficio e non riesce. Quindi, se chiamano di nuovo il primo processo, fallirà anche lui.

Qualcuno ha riscontrato questo tipo di problemi o ha qualche idea?

saluti,

--Damian

risposta

1

Quello che credo che sta accadendo qui è che il canale è timeout (come si sospetta).

Se ho capito bene, non è la chiamata per servire Un che stanno cronometrando fuori, ma piuttosto per il servizio B, prima si chiama il proprio funzionamento.

Sto indovinando che si sta creando il canale prima di si chiama il servizio A, piuttosto che appena in tempo (vale a dire prima di chiamare il servizio B). Si dovrebbe creare il canale (proxy, client di servizio) poco prima di usarla come:

AResponse aResp = null; 
BResponse bResp = null; 
using (ServiceAProxy proxyA = new ServiceAProxy()) 
{ 
    aResp = proxyA.DoServiceAWork(); 
    using (ServiceBProxy proxyB = new ServiceBProxy()) 
    { 
     bResp = proxyB.DoOtherork(aResp); 
    } 
} 
return bResp; 

io credo però, che una volta che si ottiene oltre che problema (servizio B timeout), vi renderete conto che il proxy dell'app sharepoint (chiamato servizio A) verrà sospeso. Per risolvere ciò, è possibile modificare il modello di servizio da una richiesta-risposta a un modello di sottoscrizione-pubblicazione.

Con servizi a esecuzione prolungata, è necessario che l'app sharepoint sottoscriva il servizio A e il servizio A pubblichi i risultati quando è pronto a farlo, indipendentemente dal tempo necessario.

programmazione WCF Services (O'Reilly) da Juval Lowey, ha una grande spiegazione, e Idesign (la società di Juval) ha pubblicato a great set of coding standards for WCF, così come il codice per una grande Publish-Subscribe Framework.

Spero che questo aiuti, Assaf.

5

10 minuti è il timeout di ricezione predefinito. Se si dispone di un proxy inattivo per più di 10 minuti, la sessione di sicurezza di quel proxy viene interrotta dal server. Abilita la registrazione e lo vedrai nel registro di diagnostica del server. Il messaggio di errore che hai segnalato si adatta a questo comportamento. Cerca il file di diagnostica del sistema per "SessionIdleManager". Se lo trovi, quanto sopra è il tuo problema.

Dagli un vortice e imposta establishSecurityContext = "false" per il client e il server.

3

Non chiamare l'operazione di servizio in un'istruzione using. Utilizzare invece un modello come ad esempio ...

client = new ServiceClient("Ws<binding>") 
try 
{ 
    client.Operation(x,y); 
    client.Close(); 
} 
catch() 
{ 
    client.Abort(); 
} 

Non capisco perché questo funziona, ma direi che quando il proxy va fuori del campo di applicazione nella istruzione using, Close non viene chiamato.Il servizio quindi attende fino a quando receiveTimeout (sull'associazione) è scaduto e quindi interrompe la connessione causando l'esito negativo delle chiamate successive.

+0

Ho smesso di lavorare con Uso della statistica per il servizio. Se devo eliminarlo, chiama il servizio esplicito ((IDispose)) .Dispose(); alla fine –

+1

Il problema con l'istruzione using è che se si ha un'eccezione durante la chiamata, l'istruzione using chiamerà Dispose() sul client, che chiamerà Close() sul canale sottostante. Poiché la connessione è già in errore, verrà generata un'altra eccezione e quindi la prima eccezione non verrà mai visualizzata. – flayn

0

In realtà ho attivato questo errore proprio ora facendo qualcosa di sciocco. Ho un test unitario che modifica la data del sistema per testare alcune funzionalità basate sul tempo. E credo che l'apparente differenza di tempo tra quando ho creato il contesto e quando ho chiamato il mio metodo (a causa delle modifiche alla data di sistema), ha causato la scadenza di qualcosa.