ASP.NET: Session.SessionID змінюється між запитами


142

Чому властивість SessionID на сесії -об'єкт на сторінці ASP.NET змінюється між запитами?

У мене така сторінка:

...
<div>
    SessionID: <%= SessionID %>
</div>
...

І вихід постійно змінюється щоразу, коли я натискаю F5, незалежно від браузера.

Відповіді:


225

Це причина

Під час використання стану сеансу на основі файлів cookie ASP.NET не виділяє сховище для даних сеансу, поки не буде використаний об'єкт Session. Як результат, новий ідентифікатор сеансу генерується для кожного запиту сторінки до доступу до об'єкта сеансу. Якщо у вашій програмі потрібен статичний ідентифікатор сеансу для всього сеансу, ви можете застосувати метод Session_Start у файлі Global.asax програми та зберігати дані в об’єкті Session, щоб виправити ідентифікатор сеансу, або ви можете використовувати код в іншій частині своєї додаток для явного зберігання даних в об'єкті Session.

http://msdn.microsoft.com/en-us/library/system.web.sesionstate.httpsesionstate.sessionid.aspx

Таким чином, якщо ви не отримаєте доступ до об'єкта сеансу в бекенде, з кожним запитом буде генеруватися новий ідентифікатор session

EDIT

Цей код потрібно додати у файл Global.asax. Він додає запис до об’єкта Session, щоб ви виправили сеанс, поки він не закінчиться.

protected void Session_Start(Object sender, EventArgs e) 
{
    Session["init"] = 0;
}

23
Я цього не знав, ніколи не мав проблеми з цим, але що цікаво знати
Pharabus

1
@Cladudio ви могли б просто вписати один рядок коду, і ваша відповідь ідеальна. Цікава інформація, що виходить із цікавого питання ... плюс одна? ;)
Себ Нільссон

2
Цікаво, що це виправляє мою проблему - але проблема виявилася лише через 6 місяців використання бази даних без проблем. Я не можу придумати жодної причини, чому це раптом змінилося б - може хтось запропонувати причину, чому сессионид раптом перезавантажиться, коли б цього не було раніше?
Moo

2
@KumarHarsh: щойно ви зберігаєте будь-який об’єкт на сеансі, ідентифікатор сеансу буде виправлений. Ось що я мав на увазі сказати "якщо ви не отримаєте доступ до об'єкта сеансу на бекенді ...". Як тільки ви призначите someidсеанс, якщо він залишиться таким же. Враховуйте, що цій відповіді більше 4 років, не впевнений, чи були якісь зміни стосовно цього.
Клаудіо Реді

9
Я помітив, що просто додавання методу Session_Start З НІЧОГО ІНТУ в мій Global.asax зробило цю роботу. Дякую @Claudio за пораду, хоча.
Педро

92

Є ще одна, більш підступна причина, чому це може статися навіть тоді, коли об’єкт сесії був ініціалізований, як показав Cladudio.

У Web.config, якщо є <httpCookies>запис, встановлений, requireSSL="true"але ви фактично не використовуєте HTTPS: для конкретного запиту cookie сеансу не надсилається (або, можливо, не повертається, я не впевнений, що), що означає що ви закінчуєте абсолютно новим сеансом для кожного запиту.

Я виявив цей складний шлях, витративши кілька годин, переходячи назад і назад між декількома комісіями в своєму контролі джерела, поки я не виявив, які конкретні зміни порушили мою програму.


5
Я знав це, але все одно забув це кожні 3 місяці або близько того і витратив пару годин на налагодження ..
sotn

У моєму випадку я проводив тестування на localhost, а "RequSSL" в web.config було встановлено як "вірно". Дякую.
Вільям Перейра

це був мій випадок, і я витратив занадто багато часу, намагаючись розібратися в цьому (мала червону оселедець з різними файлами web.config).
jmoreno

Ваша пропозиція вище все ще допомагає у 2018 році. Це найчастіший сценарій. Дякую!
Vijay Bansal

5

У моєму випадку я зрозумів, що в файлі cookie сесії був домен, що включає www.префікс, а я запитував сторінку з no www..
Додавання www.до URL-адреси негайно вирішило проблему. Пізніше я змінив домен файлу cookie, який потрібно встановити .mysite.comзамість www.mysite.com.


5

моя проблема полягала в тому, що у нас був цей набір у web.config

<httpCookies httpOnlyCookies="true" requireSSL="true" />

це означає, що при налагодженні в не-SSL (за замовчуванням) файл cookie auth не буде повернений на сервер. це означатиме, що сервер буде надсилати клієнту новий авторський cookie (з новим сеансом) для кожного запиту.

виправлення полягає в тому, щоб встановити Requiressl на false у web.config та true у web.release.config або включити SSL під час налагодження:

включити SSL


Чим це відрізняється від відповіді Невіла Кука від 2011 року?
Ян Кемп

4

Використовуючи відповідь Невілла (видалення RequSSL = true, в web.config) і трохи змінивши код Джоела Етертона, ось код, який повинен обробляти сайт, який працює як у режимі SSL, так і в режимі без SSL, залежно від користувача та сторінки (я Я стрибаю назад у код і ще не перевіряв його на SSL, але сподіваюся, що він повинен працювати - пізніше буде занадто зайнятим, щоб повернутися до цього, ось ось:

if (HttpContext.Current.Response.Cookies.Count > 0)
        {
            foreach (string s in HttpContext.Current.Response.Cookies.AllKeys)
            {
                if (s == FormsAuthentication.FormsCookieName || s.ToLower() == "asp.net_sessionid")
                {
                    HttpContext.Current.Response.Cookies[s].Secure = HttpContext.Current.Request.IsSecureConnection;
                }
            }
        }

2

Іншою можливістю, яка змушує SessionID змінюватись між запитами, навіть коли визначено Session_OnStart та / або ініціалізацію сесії, є те, що ім'я хоста URL містить недійсний символ (наприклад, підкреслення). Я вважаю, що це специфічне для IE (не перевірено), але якщо ваша URL-адреса, скажімо http://server_name/app, тоді IE заблокує всі файли cookie, і інформація про сеанс не буде доступною між запитами.

Насправді кожен запит розпочне окремий сеанс на сервері, тому якщо на вашій сторінці є кілька зображень, тегів сценарію тощо, то кожен із цих запитів GET призведе до іншого сеансу на сервері.

Додаткова інформація: http://support.microsoft.com/kb/316112


2

У моєму випадку це було багато в моїх розробках та тестових умовах. Спробувавши всі вищеперелічені рішення без успіху, я виявив, що мені вдалося виправити цю проблему, видаливши всі сесійні файли cookie. Розширення для веб-розробників робить це дуже просто. Я здебільшого використовую Firefox для тестування та розробки, але це траплялося і під час тестування в Chrome. Виправлення також працювало в Chrome.

Мені цього ще не доводилося робити у виробничому середовищі, і я не отримував жодних повідомлень про те, що люди не зможуть увійти. Це також, здавалося, відбулося лише після того, як сесійні файли cookie були захищені. Ніколи не бувало в минулому, коли вони не були захищеними.


Оновлення: це почалося лише після того, як ми змінили cookie сеансу, щоб забезпечити його безпеку. Я визначив, що саме ця проблема була викликана тим, що в браузері було два чи більше сеансових файлів cookie з однаковим шляхом та доменом. Завжди завжди була проблема, яка мала порожнє або нульове значення. Після видалення цього певного файлу проблема була вирішена. Я також додав код у метод Global.asax.cs Sessin_Start, щоб перевірити наявність цього порожнього файлу cookie та, якщо так, встановити його термін придатності для чогось раніше.
Метт Л

2

у моєму випадку це було тому, що я змінював сеанс після перенаправлення із шлюзу у зовнішньому додатку , тому, що я використовував IP замість localhost у цій сторінці URL, насправді вважався різним веб-сайтом з різними сеансами.

Підводячи підсумок

зверніть більше уваги, якщо ви налагоджуєте розміщену програму на IIS замість IIS express та змішуєте вашу машину http: // Ip та http: // localhost на різних сторінках


1

Моя проблема стосувалася програми IPTV для Microsoft MediaRoom. Виявляється, що MPF-програми MRML не підтримують файли cookie; змінивши використання сеансів без cookie в web.config вирішило мою проблему

<sessionState cookieless="true"  />

Ось НАДАЛЬНА стара стаття про це: Cookieless ASP.NET


1

Я перебуваю на .NET Core 2.1 і добре розумію, що питання не в Core. Але Інтернету бракує, і Google привів мене сюди, сподіваючись врятувати когось на кілька годин.


Startup.cs

services.AddCors(o => o.AddPolicy("AllowAll", builder =>
            {
                builder
                    .WithOrigins("http://localhost:3000")     // important
                    .AllowCredentials()                       // important
                    .AllowAnyMethod()
                    .AllowAnyHeader();       // obviously just for testing
            }));

client.js

const resp = await fetch("https://localhost:5001/api/user", {
            method: 'POST',
            credentials: 'include',                           // important
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
        })

Controllers/LoginController.cs

namespace WebServer.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        [HttpPost]
        public IEnumerable<string> Post([FromBody]LoginForm lf)
        {
            string prevUsername = HttpContext.Session.GetString("username");
            Console.WriteLine("Previous username: " + prevUsername);

            HttpContext.Session.SetString("username", lf.username);

            return new string[] { lf.username, lf.password };
        }
    }
}

Зауважте, що написання та читання сеансу працює, але, схоже, жодне cookie не передається браузеру. Принаймні я ніде не міг знайти заголовок "Set-Cookie".


1

Це змінювалося для мене, починаючи з .NET 4.7.2, і це було пов’язано з властивістю SameSite на файлі cookie сесії. Дивіться тут для отримання додаткової інформації: https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/

Значення за замовчуванням змінилося на "Lax" і почало ламати речі. Я змінив його на "Немає", і все працювало як очікувалося.


0

Будьте впевнені, що у вас немає дуже короткого затримки сеансу, а також переконайтесь, що якщо ви використовуєте сеанси на основі файлів cookie, ви приймаєте сеанс.

Веб-програма FireFox webDeveloperTool корисна в такі періоди, як ви можете бачити файли cookie, встановлені для вашої програми.


2
Гадаю, час мого сеансу не встановлений нижче однієї секунди. Він змінюється з кожним швидким натисканням на F5.
Себ Нільссон

0

Скидання ідентифікатора сесії може мати багато причин. Однак будь-яке згадане вище не стосується моєї проблеми. Тому я опишу це для подальшого ознайомлення.

У моєму випадку новий сеанс, створений для кожного запиту, призводив до нескінченного циклу переадресації. Дія переспрямування відбувається в події OnActionExecuting .

Також я очищав усі заголовки http (також у події OnActionExecuting, використовуючи метод Response.ClearHeaders ), щоб запобігти кешування сайтів на стороні клієнта. Але цей метод очищає всі заголовки, включаючи інформацію про сеанс користувача, а отже, і всі дані у сховищі Temp (які я використовував пізніше в програмі). Тож навіть налаштування нового сеансу у події Session_Start не допомогло.

Щоб вирішити свою проблему, я забезпечив не видаляти заголовки, коли відбудеться перенаправлення.

Сподіваюся, це комусь допоможе.


0

Я зіткнувся з цим питанням по-іншому. Контролери, які мали цей атрибут [SessionState(SessionStateBehavior.ReadOnly)], читали з іншого сеансу, хоча я встановив значення в початковому сеансі при запуску програми. Я додавав значення сеансу через _layout.cshtml (можливо, не найкраща ідея?)

Очевидно, що проблема ReadOnly викликала проблему, оскільки коли я видалив атрибут, оригінальний сеанс (і SessionId) залишився б у такт. За допомогою рішення Клаудіо / Майкрософт це виправили.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.