Сеансы Asp.net, пересекающиеся/смешанные

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

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

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

Немного о нашем коде:
Как и в любом другом приложении, у нас есть простая страница входа, в которую пользователь вводит адрес электронной почты и пароль, и мы аутентифицируем их по нашей базе данных, и если они действительны, мы вызываем 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));
}

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

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

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

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

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

P.S- Приложение работает под управлением Windows 2008 R2 с IIS 7.5. И мы НЕ, используя cookieless session.

Ответы

Ответ 1

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

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

Была линия, которую мы использовали <%@ OutputCache NoStore="true" Duration="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);

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

Ответ 2

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

Ответ 3

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

В моем случае это не имело значения, если использовать sessionStat InProc ore StateServer, если у вас есть cookieless или cookie-сессии.

Ответ 4

У нас была та же проблема в компании, в которой я работаю. Мы также поняли, что это было вызвано кэшированием вывода, в результате чего кто-то другой 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-заголовок, содержащий набор -Кукивный ответ

Что описывает симптом как:

Рассмотрим следующий сценарий. Страница 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 - почему это происходит и что можно сделать с этим?

Ответ 5

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

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");

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

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

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

Ответ 6

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

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

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

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

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

Ответ 7

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

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

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

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

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

fooobar.com/info/174513/...

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