2012-11-13 5 views
17

E 'possibile distruggere una connessione persistente che è stata creata con NSURLConnection? Devo essere in grado di distruggere la connessione persistente e fare un altro handshake SSL.Come cancellare una connessione persistente usando NSURLConnection?

Come ora, chiamando [conn cancel] lascia una connessione persistente dietro che viene utilizzata con la successiva richiesta di connessione a quell'host, che non voglio che accada.

+0

Ho lo stesso problema. Ho provato diverse correzioni ma finora nessuno di loro ha funzionato. – EricS

risposta

16

Come risulta, credo che la cache della sessione TLS di Secure Transport sia la causa.

Ho anche posto la domanda on the apple developer forums e ho ricevuto una risposta da una persona Apple. Lui mi ha indicato questo Apple sample code readme dove si dice:

In fondo alla pila TLS su entrambi iOS e Mac OS X è un componente conosciuto come un trasporto sicuro. Secure Transport gestisce una cache di sessione TLS per processo. Quando ci si connette tramite TLS, la cache memorizza le informazioni sulla negoziazione TLS in modo che le connessioni successive possano connettersi più rapidamente. Il meccanismo on-the-wire è descritto nel link sottostante.

http://en.wikipedia.org/wiki/Transport_Layer_Security#Resumed_TLS_handshake

Questo presenta alcuni trucchi interessanti, soprattutto mentre si sta debug. Ad esempio, si consideri la seguente sequenza:

  1. È possibile utilizzare la scheda Debug per impostare il server di convalida TLS su Disabilitato.

  2. Connessione a un sito con un'identità autofirmata. La connessione ha esito positivo perché hai disabilitato la convalida del trust del server TLS. Aggiunge una voce alla cache della sessione TLS di Secure Transport.

  3. Si utilizza la scheda Debug per impostare la Convalida del server TLS su Predefinito.

  4. Si collega immediatamente allo stesso sito come nel passaggio 2. Ciò non dovrebbe riuscire, a causa della modifica nel criterio di convalida della fiducia del server, ma ha esito positivo perché non si riceve mai una richiesta NSURLAuthenticationMethodServerTrust. Sotto le copertine, Secure Transport ha ripreso la sessione TLS, il che significa che la sfida non salirà mai al livello.

  5. D'altra parte, se si ritarda per 11 minuti tra i passaggi 3 e 4, le cose funzionano come previsto (beh, fallire come previsto :-). Questo perché la cache della sessione TLS di Secure Transport ha un timeout di 10 minuti.

Nel mondo reale questo non è un problema enorme, ma può essere molto confuso durante il debug. Non esiste un modo programmatico per svuotare la cache della sessione TLS di Secure Transport ma, poiché la cache è per processo, è possibile evitare questo problema durante il debug semplicemente abbandonando e rilanciando l'applicazione. Ricorda che, a partire da iOS 4, la pressione del pulsante Home non chiude necessariamente la tua applicazione. Invece, dovresti uscire dall'applicazione dall'elenco delle applicazioni recenti.

Quindi, in base a ciò, un utente dovrebbe o uccidere la propria app e riavviarlo o attendere più di 10 minuti prima di inviare un'altra richiesta.

Ho fatto un'altra ricerca su Google con questa nuova informazione e ho trovato this Apple technical Q&A article che corrisponde esattamente a questo problema. Vicino al fondo, si menziona l'aggiunta di un 'finale'. ai nomi di dominio (e, auspicabilmente, agli indirizzi IP) per le richieste al fine di forzare un errore nella cache della sessione TLS (se non riesci a modificare il server in qualche modo, cosa che non posso), quindi ho intenzione di provare questo e spero che sia funzionerà. Pubblicherò le mie scoperte dopo averlo testato.

### EDIT ###

ho provato l'aggiunta di un '' alla fine dell'indirizzo ip e la richiesta è stata ancora completata con successo.

Ma stavo pensando al problema in generale e non c'è davvero alcun motivo per forzare un altro handshake SSL. Nel mio caso, la soluzione a questo problema è di conservare una copia dell'ultimo SecCertificateRef noto che è stato restituito dal server. Quando si effettua un'altra richiesta al server, se viene utilizzata una sessione TLS memorizzata nella cache (non è stato chiamato connection:didReceiveAuthenticationChallenge:), sappiamo che lo SecCertificateRef salvato è ancora valido. Se si chiama connection:didReceiveAuthenticationChallenge:, possiamo ottenere il nuovo SecCertificateRef in quel momento.

-3

In primo luogo, si dovrebbe usare [self.conn cancel] e in secondo luogo, ciò fa esattamente quello che dice. Si annulla. Se non vuoi più usare NSURLConnection, non farà nulla e se lo userai di nuovo, puoi semplicemente impostare una richiesta diversa, che si connetterà al server specificato.

Spero che questo aiuti.

+0

Forse non ho spiegato abbastanza chiaramente la mia domanda. L'oggetto NSURLConnection (conn) viene cancellato correttamente, ma la connessione socket sottostante rimane aperta e viene riutilizzata la prossima volta che creo NSURLConnection sullo stesso host. Questo è un problema perché a volte ho bisogno di fare un altro handshake SSL con l'host, e dal momento che sta riutilizzando la connessione, l'handshake è già stato fatto. – jblack

0

A partire da OS X 10.9, NSURLSession è la soluzione.