Сессии Asp.net становятся пересеченными / перепутаны - PullRequest
16 голосов
/ 07 апреля 2011

Несколько недель назад к нам обратился один из наших клиентов, который сказал, что иногда, когда он создает действие, оно создается под чужим именем!

Мы решили проблему и ничего не нашли.Мы попросили пользователя связаться с нами в следующий раз, когда он столкнется с этими проблемами.Он связался с нами, и мы смогли устроить с ним встречу и увидеть проблему своими глазами.

Это были не только действия, он был признан кем-то еще в приложении.У него был доступ ко всему, что должен был иметь другой человек.Именно тогда мы поняли, что у нас возникла проблема со сессией.

Немного о нашем коде:
Как и у любого другого приложения, у нас есть простая страница входа, где пользователь вводит адрес электронной почты и пароль, и мы аутентифицируем ихдля нашей базы данных, и если они действительны, мы вызываем FormsAuthentication.SetAuthCookie (), чтобы сохранить текущий идентификатор пользователя в файле cookie, и мы его впускаем.

BL.User currentUser = BL.User.Authenticate(txtUsername.Text, txtPassword.Text);

if (currentUser != null)
{
    this.Session["NumberOfLoginTried"] = "0";
    FormsAuthentication.SetAuthCookie(currentUser.UserID.ToString(), chRememberMe.Checked);
    Response.Redirect(FormsAuthentication.GetRedirectUrl(currentUser.UserID.ToString(), false));
}

Мы также используем следующий фрагмент кода для входа в систему:в ID пользователя (текущий пользователь) в нашем приложении.

public static int GetCurrentUserID()
{
    int userID = -1;
    int.TryParse(HttpContext.Current.User.Identity.Name, out userID);
    return userID;
}

И да, мы сделали нашу домашнюю работу и погуглили и увидели следующие две ссылки:

http://lionsden.co.il/codeden/?p=446
Сеанс ASP.NET с использованием StateServer (SCARY!)

Мы отключили кэширование в режиме ядра и в режиме пользователя для файлов .aspx и .ascx, и это все еще происходит.

PS - Приложение работает на Windows 2008 R2 с IIS 7.5.И мы НЕ используем сеанс без файлов cookie.

Ответы [ 7 ]

13 голосов
/ 10 мая 2011

У нас только что была очень похожая проблема, которая возникала случайно, казалось бы, невоспроизводимо.

Проблема оказалась в механизме кэширования страниц ASP.NET - в нашем случае, в частности, в теге <%@ OutputCache.

Была линия, которую мы использовали <%@ OutputCache NoStore="true" Duration="1" %>, что в основном означало, что если два пользователя обращались к одной и той же странице в течение 1 секунды друг от друга, они видели бы одну и ту же страницу (включая зарегистрированное имя пользователя другого пользователя). Поэтому, если они обновили указанную страницу, они получили правильную информацию.

В нашем случае изменение указанной строки на <%@ OutputCache NoStore="true" Duration="1" VaryByParam="*" %>, отключение кеширования ядра в IIS как по этой ссылке (http://lionsden.co.il/codeden/?p=446)

и добавление следующих строк к событию Page_Load рассматриваемой страницы:

Response.CacheControl = "private";
Response.ExpiresAbsolute = DateTime.Now.AddDays(-1d);
Response.Cache.SetCacheability(HttpCacheability.NoCache);

Кажется, мы решили эту проблему. Надеюсь, это поможет кому-то еще с подобной проблемой.

4 голосов
/ 10 января 2013

У нас была та же проблема, и она была вызвана параметром <clientCache/> в IIS, который по умолчанию не может добавить HTTP-заголовок Cache-Control: private. Отсутствие этого заголовка означало, что наши файлы cookie для проверки подлинности с помощью форм кэшировались прокси-серверами нижестоящего уровня! Поэтому, когда наш сайт стал занятым, внезапно множество пользователей внезапно вошли как неправильный пользователь! Кошмар.

3 голосов
/ 01 декабря 2016

У нас была такая же проблема в компании, в которой я работаю.Мы также поняли, что это было вызвано кэшированием вывода, которое привело к отправке чужого SessionId не тому человеку.

Теперь мы добавили следующий элемент <caching> в наш web.config.

<configuration>
  [...]
  <system.webServer>
    [...]
    <caching enabled="false" enableKernelCache="false">
    </caching>
  </system.webServer>
  [..]
</configuration>

Мы не можем гарантировать, что это решит ее, потому что проблему практически невозможно воспроизвести, но, исходя из наших исследований, это должно решить ее.

Странно, ссылка настатья Microsoft, описывающая эту проблему, которую можно найти в Интернете, дает некоторую общую страницу, как если бы страница была удалена.

Но есть эта статья Microsoft, которая, кажется, описывает ту же проблему в IIS 6:

Страница ASP.NET сохраняется в кэше ядра HTTP.sys в IIS 6.0, когда страница ASP.NET создает заголовок HTTP, содержащий ответ Set-Cookie

Который описывает симптом как:

Рассмотрим следующий сценарий.Страница Microsoft ASP.NET содержит директиву <% @ OutputCache%>.Кроме того, страница ASP.NET создает заголовок HTTP, который содержит ответ Set-Cookie.В этом случае страница ASP.NET хранится в кэше ядра стека протоколов HTTP (HTTP.sys) в Microsoft Internet Information Services (IIS) 6.0.Поэтому несколько пользователей, получающих доступ к одной и той же странице, могут получать идентичные файлы cookie.

Обновление

Я нашел эту действительно хорошую статью в блоге Microsoft Premier Developer, в которой объясняетсялот:

Обмен сеансами ASP.Net - почему это происходит и что с этим можно сделать?

3 голосов
/ 29 января 2012

, если вообще удалить <%@ OutputCache NoStore="true" Duration="1" VaryByParam="*" (во всех файлах ascx, находящихся в строке от Master к aspx тоже !!!), предотвратить перекрестные сеансы. при наличии только одного ascx с загруженной директивой outputcache произошли перекрестные сеансы.

В моем случае это не имело значения, если вы используете sessionstat InProc или StateServer, если у вас есть сессии без файлов cookie или файлов cookie.

2 голосов
/ 26 апреля 2011

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

Вы можете прекратить использование сеанса ASP.NET для хранения ваших идентификаторов.

У вас есть несколько вариантов, где вы могли бы хранить эту информацию вместо этого. Вы можете зашифровать его в свойстве UserData билета проверки подлинности с помощью форм (я делал это раньше в работе, оно отлично подходит для хранения ключа (ключей), csv ролей или даже небольших объектов json). Если вы заполнили форму для проверки подлинности формы, вы можете написать информацию непосредственно в виде своего собственного файла cookie. Вы также можете вообще обойти куки.

Если вы решите обойти файлы cookie, вы в основном вступаете на аналогичную территорию сеансов ASP.NET без файлов cookie. У вас есть пара опций, вы можете сделать так, чтобы идентификатор пользователя был отдельным от каждого URL в качестве параметра запроса. Другой вариант - создать HttpModule, который бы добавлял скрытую форму ввода в каждый ответ на странице, содержащий идентификатор зарегистрированного пользователя.

Если вы идете по пути без файлов cookie, убедитесь, что невозможно использовать ваш сайт в качестве HTTP, и каждый отдельный запрос - HTTPS. Тем более, если вы используете метод параметра запроса.

2 голосов
/ 07 апреля 2011

Поскольку вы все отключили кэширование в режиме ядра, я хотел бы отметить некоторые другие соображения.

1) Чтобы правильно использовать HttpContext.Current.User.Identity.Name, сначала необходимо убедиться, что ваш пользователь вошел в систему, используяUser.Identity.IsAuthenticated

2) в этот момент Session.Add("CurrentUser", currentUser); что вы на самом деле пытаетесь сохранить?

Теперь я думаю, что проблема в кеше.Страницы хранятся где-то между вашими пользователями, и одна смешивается с другой.Некоторые заголовки, которые вы можете использовать на своей странице, чтобы избежать кэширования на средних прокси-компьютерах.

Response.Cache.SetExpires(DateTime.UtcNow.AddYears(-2));
Response.Cache.SetNoStore();
Response.Cache.SetValidUntilExpires(false);
Response.Cache.SetCacheability(HttpCacheability.NoCache);                
Response.ExpiresAbsolute = DateTime.Now.Subtract(new TimeSpan(1, 0, 0, 0));
Response.Expires = 0;
Response.CacheControl = "no-cache";
Response.AppendHeader("Pragma", "no-cache");

Также я говорю, что если на ваших страницах есть данные, которыми вы не хотите делиться среди своих пользователей, вынеобходимо использовать защищенные HTTPS-страницы и настроить файлы cookie на доступность только на защищенных страницах, добавив <httpCookies httpOnlyCookies="true" requireSSL="true" /> на web.config

Кроме того, проверьте, сохраняете ли вы сеанс на сервере SQL, который вы запланировали запуститьдо маршрутизации каждую 1 минуту.

Чтобы найти больше информации, я предлагаю сохранить некоторый скрытый текст на страницах, например дату и время отрисовки, возможно, последние 4 цифры идентификатора пользователя,и что еще, возможно, поможет вам понять, была ли страница из кэша или нет.

0 голосов
/ 10 июля 2017

Если вы проверили, что кэширование вывода не является проблемой

Здесь уже есть ответ от меня, но, как оказалось, мое другое решение (отключение кэша вывода) на самом деле не решило нашу проблему за нас.

Так как в вопросе указано, что кэширование отключено, единственная другая возможная (AFAIK) ошибка, которая может привести к этому, - то, что оказалось настоящим виновником в нашем случае: мы используем закрытую переменнуюв ActionFilterAttribute.

И поскольку они кэшируются, хранение личных / личных данных пользователя таким образом также может привести к перепутыванию сеансов!

Этот ответ описывает, в чем заключалась наша проблема и как ее исправить:

https://stackoverflow.com/a/8937793/1864395

Кроме того, я думаю, что стоит упомянуть, что мы смогли воспроизвести проблему, запустив Apache JMeter со сценарием для нескольких пользователей нав то же время.Это действительно хороший инструмент (хотя и не очень удобный для пользователя / интуитивно понятный), используемый для (среди прочего) стресс-тестирования. Вероятно, это единственный способ диагностировать перепутывание сессий!

...