Почему / когда сеансовые записи уязвимы для завершения потока? - PullRequest
5 голосов
/ 15 февраля 2010

КОД:

Session["foo"] = "bar";  
Response.Redirect("foo.aspx");

ПРОБЛЕМА:

Когда foo.aspx читает «foo» из сеанса, его там нет. сеанс есть, но для «foo» нет значения.

Я наблюдал это периодически в нашей производственной среде. Но я не хочу задавать вопрос о Response.Redirect () .

ОБЪЯСНЕНИЕ:

Бертран Ле Руа объясняет (смелость моя):

Теперь Redirect отправляет специальный заголовок для клиента, чтобы он запрашивает у сервера другой страница, чем та, которую он ждал. На стороне сервера, после отправки этого Заголовок, Redirect завершает ответ. Это очень жестокая вещь. Response.End фактически останавливает выполнение страницы, где бы она ни находилась используя ThreadAbortException. Какие на самом деле здесь происходит то, что жетон сессии теряется в битве.

Мой вывод: Response.Redirect () может быть жестким с конечными потоками. И это может поставить под угрозу мою сессионную запись, если они произойдут слишком близко к этой жесткости.

ВОПРОС:

Как насчет управления сеансами ASP.NET делает его настолько уязвимым для этого? Строка кода Response.Redirect () не начинает свое выполнение, пока строка записи сеанса не будет «закончена» - как это может быть такой угрозой моей записи сеанса?

А как насчет того, что запись сеанса не "завершается" до выполнения следующей строки кода? Существуют ли другие сценарии, в которых записи сеанса аналогично (как будто они никогда не происходили) теряются?

Ответы [ 3 ]

2 голосов
/ 15 февраля 2010

Я недостаточно знаком с внутренностями записи сеанса, но я предполагаю, что у него есть некоторые сложности, поскольку он основан на преобразовании файлов cookie сеанса браузера в идентификацию сервера. Кроме того, ThreadAbortExceptions имеет особые соображения во время выполнения, которые могут играть здесь, я не уверен.

В любом случае, Response.Redirect() имеет перегрузку, которая принимает логический параметр, который позволяет вам указать, хотите ли вы завершить поток или нет.

Response.Redirect(string url,  bool endResponse);

Если вы вызовете его с endResponse, установленным в «false», он будет аккуратно закончен, вместо внутреннего * вызова 900. Однако это означает, что он также выполнит любой код, оставленный в жизненном цикле страницы перед завершением.

Хороший компромисс - позвонить Response.Redirect(url, false), а затем Application.CompleteRequest(). Это позволит вашему перенаправлению произойти, но также изящно закроет текущий контекст выполнения с минимальной дополнительной обработкой жизненного цикла.

1 голос
/ 22 ноября 2010

После тестирования нескольких альтернатив (Response.Redirect (..., false), Server.Transfer () и других «решений», которые я сейчас не могу вспомнить), мы нашли только один надежный ответ на эту проблему.

Перемещение нашего состояния сеанса из InProc в SqlServer эффективно устраняет это поведение в наших системах, оставляя Response.Redirect (...) полностью надежным. Если дальнейшее тестирование покажет обратное, я сообщу здесь, но я скажу, чтобы это перестало происходить в вашей среде: переместите ваше состояние сеанса в SqlServer (или достаточно "вне InProc"? Я не уверен).

0 голосов
/ 16 февраля 2010

Повторное использование пула приложений может привести к прекращению сеанса. Вы можете настроить пул приложений на перезапуск в фиксированное время (рекомендуется, ночью или в периоды низкой нагрузки) или увеличить период ожидания перезапуска пула приложений.

...