Страницы

Поиск по вопросам

понедельник, 22 октября 2018 г.

SslStream, как отключить кэширование сеанса?

В документации сказано:
Платформа Framework кэширует сеансы SSL при их создании и пытается повторно использовать кэшированный сеанс для нового запроса, если это возможно. При попытке повторного использования сеанса SSL платформа Framework использует первый элемент ClientCertificates (если таковой существует) или пытается повторно использовать анонимные сеансы при пустом значении ClientCertificates.
Как отключить кэширование?
В данный момент есть проблемы с повторным подключением к серверу (т.е. при первом подключении все проходит удачно, при повторном - сервер рвет сессию. Если перезапустить приложение - опять первое подключение удачно, повторное - разрыв сессии), думаю проблема либо в кэшировании, либо SslStream досих пор не пофиксили и клиент не закрывает корректно сессию: ссылка
Update
Дело 100% в кэшировании сессии!
Дошли руки, проверил сниффером пакеты. Различаются сообщения типа Client Hello в одном месте.
Первое подключение к серверу (успешное): скриншот
Второе подключение к серверу без перезапуска программы (не успешное): скриншот
Думаю различие в идентификаторе сессии видно невооруженным взглядом.
p.s. очень не хочется использовать сторонние ssl клиенты. Есть ли разумный выход из ситуации?


Ответ

К сожалению, кеширование происходит во внутреннем классе, и честно говоря не нашел в коде каких-либо точек, позволяющих его отключить полностью. Как вариант - можете между подключениями чистить кеш через Reflection:
var sslAssembly = Assembly.GetAssembly(typeof(SslStream));
var sslSessionCacheClass = sslAssembly.GetType("System.Net.Security.SslSessionsCache");
var cachedCredsInfo = sslSessionCacheClass.GetField("s_CachedCreds", BindingFlags.NonPublic | BindingFlags.Static); var cachedCreds = (Hashtable)cachedCredsInfo.GetValue(null);
cachedCreds.Clear();
Хотя конечно тоже костыль.. Вообще вся эта история с отключением кеширования сеансов является бооольшим костылем. Оно не должно никогда отключатся для клиента.
Самым правильным решением было бы исправление проблемы внутри серверной части. Попробуйте поговорить с разработчиками серверного приложения к которому вы подключаетесь.
Обновлено: В случае с многопоточностью, можно ещё больше "закостылится", создав заглушку для Hashtable, ничего в себя не сохраняющую:
public class DummyHashtable : Hashtable { public override object this[object key] { get { return null; } set { return; } }
public override void Add(object key, object value) { return; } }
Ну и соответственно вместо GetValue()/Clear() просто подменить значение этого поля:
var dummyCache = new DummyHashtable(); cachedCredsInfo.SetValue(null, dummyCache);
В итоге, кеш не сработает никогда.

Комментариев нет:

Отправить комментарий