Сессии Asp.net пересекаются / смешиваются

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

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

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

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

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;
}

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

http://lionsden.co.il/codeden/?p=446
Смешивание сеанса ASP.NET с использованием StateServer (СТРАШНО!)

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

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


person Houda    schedule 07.04.2011    source источник
comment
Ваш пользователь устанавливает флажок "Запомнить меня"? И есть ли какая-то закономерность в отношении того, на какого неправильного пользователя переходит ваш пользователь (например, всегда ли это один и тот же пользователь? Это другой пользователь в том же месте (большой намек, если так), это другой пользователь, вошедший в систему, и т. Д.)?   -  person KP Taylor    schedule 07.04.2011
comment
@houda, где ты хранил сеанс? (sql, mem?) Если он на sql, запускаете ли вы скрипт автоочистки каждую минуту? Кроме того, почему ошибка связана с этими функциями? возможно, вы пропустили какую-то другую ошибку. Вы пользуетесь WebGarden? (многие процессы asp.net?)   -  person Aristos    schedule 07.04.2011
comment
@houda также существует вероятность того, что страницы хранятся на прокси-сервере, и вы, пользователи, видите страницы, сохраненные прокси-сервером предыдущего пользователя! У вас нет кеширования? а прокси не разрешены? Страницы https? Ваш клиент находится в офисе, который подключается к Интернету через прокси-маршрутизатор?   -  person Aristos    schedule 07.04.2011
comment
@houda, меня смущает ваша процедура GetCurrentUserID - почему вы ожидаете, что HttpContext.Current.User.Identity.Name будет разбираться с int? Кроме того, если TryParse завершится неудачно, он установит для userID значение 0, а не оставит его равным -1.   -  person Andrew    schedule 07.04.2011
comment
@Ken Это все случайно, я не нашел ни одного шаблона.   -  person Houda    schedule 07.04.2011
comment
@Aristos Сессии сохраняются в памяти. Нет WebGarden. Проблема в том, что сеансы пересекаются. Я отслеживал идентификаторы сеансов и видел это воочию. Я собираюсь установить запрет на перехват и прокси (я точно не знаю, как это сделать, не могли бы вы направить меня в правильном направлении, пожалуйста?). Все страницы https. ДА НЕКОТОРЫЕ НАШИ КЛИЕНТЫ НАХОДЯТСЯ В ОДНОМ ОФИСЕ И МОГУТ ИМЕТЬ ПРОКСИ-МАРШРУТИЗАТОР.   -  person Houda    schedule 07.04.2011
comment
@Houda Вы решили свою проблему?   -  person Jacob Phan    schedule 19.01.2016
comment
@Hauda, ​​ты можешь решить? У меня такая же проблема.   -  person Cagdas    schedule 28.02.2017


Ответы (7)


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

Проблема оказалась в механизме кеширования страниц 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);

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

person Joebone    schedule 10.05.2011
comment
У нас была аналогичная проблема, но со смешанными запросами. VaryByParam="*" был решением. - person DavidC; 08.06.2016

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

person Ben Collins    schedule 10.01.2013

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

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

person Hans    schedule 28.01.2012

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

person Sander_P    schedule 01.12.2016

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

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 цифры идентификатора пользователя и что еще вы можете сделать, что может помочь вам увидеть, если страница взята из кеша или нет.

person Aristos    schedule 07.04.2011
comment
Session.Add (CurrentUser, currentUser) - это старая строка кода, которая больше не используется. - person Houda; 07.04.2011
comment
@Houda для не разрешенного прокси-сервера, установите этот ответ, который у меня есть в ответе здесь, возможно, вы можете найти более или менее в Интернете, но я думаю, что проблема в прокси-сервере в офисе, просто отключите кеш на страницы этими заголовками, и я думаю, вы решите эту проблему. - person Aristos; 08.04.2011
comment
@Houda также я говорю, что это лучше обработать, если вы переместите сеанс на SQL-сервер. По крайней мере, в моем случае у меня возникают проблемы при использовании InProc. - person Aristos; 08.04.2011
comment
Я добавил заголовки на все страницы. Проблема все еще возникает, но уже не так сильно, как раньше. Любое другое предложение? - person Houda; 25.04.2011
comment
Я добавил заголовки на все страницы. Проблема все еще возникает, но уже не так сильно, как раньше. Ирония заключается в том, что мы часто используем iFrame в нашем проекте, и, как вы знаете, iFrame агрессивно кэшируются; мы добавили случайную строку в конец всех URL-адресов, когда они извлекаются клиентом. Любое другое предложение? - person Houda; 25.04.2011

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

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

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

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

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

person Chris Marisic    schedule 26.04.2011
comment
Что меня действительно сбивает с толку, так это то, что информация о пользователе и идентификатор сеанса хранятся в файлах cookie, а не в состоянии. Обычно, когда я вызываю HttpContext.Current.User.Identity.Name, я обращаюсь к файлу cookie. Кэшируются ли эти файлы cookie в прокси-сервере ?! - person Houda; 28.04.2011
comment
Возможно, они кэшируются прокси-сервером, и вы должны легко это проверить. Это может сделать мое представление о добавлении идентификаторов непосредственно в форму в качестве обходного пути. Он может не кэшировать это, конечно, он также может кэшировать это. Попытки бороться с неисправными системами всегда проигрывают. - person Chris Marisic; 29.04.2011

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

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

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

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

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

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

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

person Sander_P    schedule 10.07.2017