Как отменить постоянное соединение с помощью NSURLConnection?

17

Возможно ли уничтожить постоянное соединение, которое было создано с помощью NSURLConnection? Мне нужно иметь возможность уничтожить постоянное соединение и выполнить другое квитирование SSL.

Как и сейчас, вызов [conn cancel] оставляет постоянное соединение за тем, которое используется с последующим запросом на соединение с этим хостом, чего я не хочу.

    
задан jblack 13.11.2012 в 22:46
источник
  • У меня такая же проблема. Я пробовал несколько исправлений, но пока никто из них не работает. –  EricS 14.11.2012 в 04:57

3 ответа

16

Как оказалось, я считаю, что кэш сеанса Secure Transport TLS виноват.

Я также задал вопрос на форумах разработчиков Apple и получил ответ от человека Apple. Он указал мне на этот Apple sample code readme , где говорится:

  

В нижней части стека TLS на iOS и Mac OS X есть компонент, известный как Secure Transport. Secure Transport поддерживает кеш сеанса TLS для каждого процесса. Когда вы подключаетесь через TLS, кэш хранит информацию о согласовании TLS, чтобы последующие соединения могли подключаться быстрее. Механизм на проводе описан по ссылке ниже.

     

Ссылка

     

Здесь представлены некоторые интересные ошибки, особенно при отладке. Например, рассмотрим следующую последовательность:

     
  1. Вы используете вкладку «Отладка», чтобы отключить проверку сервера TLS.

  2.   
  3. Вы подключаетесь к сайту с самозаверяющим идентификатором. Соединение выполняется успешно, поскольку вы отключили проверку доверия TLS-сервера. Это добавляет запись в кеш сеанса Secure Transport TLS.

  4.   
  5. Вы используете вкладку «Отладка», чтобы установить проверку сервера TLS по умолчанию.

  6.   
  7. Вы сразу же подключаетесь к тому же сайту, что и на шаге 2. Это должно завершиться неудачно из-за изменения политики проверки доверия сервера, но оно преуспевает, потому что вы никогда не получаете запрос NSURLAuthenticationMethodServerTrust. Под обложками Secure Transport возобновил сеанс TLS, что означает, что вызов никогда не пузырится до вашего уровня.

  8.   
  9. С другой стороны, если вы задерживаетесь на 11 минут между шагами 3 и 4, все работает так, как ожидалось (ну, как ожидалось :-). Это связано с тем, что тайник сеанса TLS Secure Transport имеет время ожидания 10 минут.

  10.   

В реальном мире это не огромная проблема, но во время отладки это может быть очень запутанным. Не существует программного способа очистки кэша сеанса Secure Transport TLS, но, поскольку кеш-процесс является процессом, вы можете избежать этой проблемы во время отладки, просто прекратив работу и перезапустив приложение. Помните, что, начиная с iOS 4, нажатие кнопки «Домой» не обязательно покидает ваше приложение. Вместо этого вы должны выйти из приложения из списка последних приложений.

Итак, на основании этого пользователю придется либо убить приложение, либо перезагрузить его, либо подождать более 10 минут, прежде чем отправлять другой запрос.

Я сделал еще один поиск по Google с этой новой информацией и нашел эту техническую статью и техническую статью Apple , который точно соответствует этой проблеме. Рядом со дном в нем упоминается добавление конечного «.». для доменных имен (и, надеюсь, IP-адресов) для запросов, чтобы заставить пропустить кеш сеанса TLS (если вы не можете каким-либо образом изменить сервер, чего я не могу), поэтому я собираюсь попробовать это и, надеюсь, это будет работать. Я опубликую свои результаты после того, как проведу это.

### EDIT ###

Я тестировал добавление '.' до конца IP-адреса, и запрос был успешно завершен.

Но я думал о проблеме в целом, и нет оснований для принудительного установления другого SSL-соединения. В моем случае решение этой проблемы - сохранить копию последнего известного SecCertificateRef, который был возвращен с сервера. При выполнении другого запроса на сервер, если используется кешированный сеанс TLS ( connection:didReceiveAuthenticationChallenge: не был вызван), мы знаем, что сохраненный SecCertificateRef по-прежнему действителен. Если вызывается connection:didReceiveAuthenticationChallenge: , в это время мы можем получить новый SecCertificateRef .

    
ответ дан jblack 14.11.2012 в 06:14
0

Начиная с OS X 10.9, NSURLSession является решением.

    
ответ дан Antoine Rosset 06.06.2016 в 08:34
-3

Во-первых, вы должны использовать     [self.conn cancel] и, во-вторых, это делает то, что он говорит. Он отменяет себя. Если вы больше не хотите использовать NSURLConnection, он ничего не сделает, и если вы снова будете использовать его, вы можете просто установить другой запрос, который будет подключаться к данному серверу.

Надеюсь, что это поможет.

    
ответ дан Finn Gaida 13.11.2012 в 23:13
  • Возможно, я недостаточно четко объяснил свой вопрос. Объект NSURLConnection (conn) полностью отменяется, но основное сокетное соединение остается открытым и повторно используется при следующем запуске NSURLConnection на том же хосте. Это проблема, потому что иногда мне нужно сделать еще одно подтверждение SSL с хостом, и поскольку он повторно использует соединение, рукопожатие уже выполнено. –  jblack 14.11.2012 в 00:27