ASP.NET: Session.SessionID zmienia się między żądaniami

142

Dlaczego własność sessionid na sesji -przedmiot w zmianie stron ASP.NET między wniosków?

Mam taką stronę:

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

Wyjście zmienia się za każdym razem, gdy naciskam klawisz F5, niezależnie od przeglądarki.

Seb Nilsson
źródło

Odpowiedzi:

225

to jest powód

W przypadku korzystania ze stanu sesji opartego na plikach cookie ASP.NET nie przydziela miejsca na dane sesji, dopóki nie zostanie użyty obiekt sesji. W rezultacie dla każdego żądania strony do momentu uzyskania dostępu do obiektu sesji generowany jest nowy identyfikator sesji. Jeśli Twoja aplikacja wymaga statycznego identyfikatora sesji dla całej sesji, możesz zaimplementować metodę Session_Start w pliku Global.asax aplikacji i przechowywać dane w obiekcie Session w celu ustalenia identyfikatora sesji lub użyć kodu w innej części aplikacji do jawnego przechowywania danych w obiekcie Session.

http://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid.aspx

Tak więc w zasadzie, jeśli nie uzyskasz dostępu do obiektu sesji na zapleczu, nowy sessionId zostanie wygenerowany z każdym żądaniem

EDYTOWAĆ

Ten kod należy dodać do pliku Global.asax. Dodaje wpis do obiektu Session, więc naprawiasz sesję, dopóki nie wygaśnie.

protected void Session_Start(Object sender, EventArgs e) 
{
    Session["init"] = 0;
}
Claudio Redi
źródło
23
Nie wiedziałem tego, nigdy nie miałem z tym problemu, ale warto wiedzieć
Pharabus
1
@Cladudio, możesz po prostu wrzucić jedną linię kodu, a Twoja odpowiedź jest idealna. Ciekawe informacje wynikające z interesującego pytania ... plus jeden? ;)
Seb Nilsson
2
Co ciekawe, to rozwiązuje mój problem - ale problem pojawił się dopiero po około 6 miesiącach bezproblemowego korzystania z bazy kodu. Nie mogę wymyślić żadnego powodu, dla którego miałoby się to nagle zmienić - czy ktoś może zasugerować powód, dla którego sessionid miałby nagle zostać zresetowany, podczas gdy wcześniej nie?
Moo
2
@KumarHarsh: po zapisaniu dowolnego obiektu w sesji identyfikator sesji zostanie naprawiony. To właśnie miałem na myśli mówiąc „jeśli nie masz dostępu do obiektu sesji na zapleczu…”. Po przypisaniu someidsesji, jeśli pozostanie taka sama. Weź pod uwagę, że ta odpowiedź ma więcej niż 4 lata, nie jestem pewien, czy była w związku z tym jakaś modyfikacja.
Claudio Redi
9
Zauważyłem, że dodanie metody Session_Start BEZ NIC W IT do mojego Global.asax sprawiło, że to zadziałało. Dzięki @Claudio za wskazówkę.
Pedro
92

Istnieje inny, bardziej podstępny powód, dla którego może się to zdarzyć nawet wtedy, gdy obiekt Session został zainicjowany, jak zademonstrował Cladudio.

W pliku Web.config, jeśli istnieje <httpCookies>wpis, który jest ustawiony na, requireSSL="true"ale w rzeczywistości nie używasz protokołu HTTPS: dla określonego żądania plik cookie sesji nie jest wysyłany (lub może nie zwracany, nie jestem pewien który), co oznacza że kończysz z zupełnie nową sesją dla każdego żądania.

Znalazłem to na własnej skórze, spędzając kilka godzin między kilkoma zatwierdzeniami w mojej kontroli źródła, dopóki nie odkryłem, jaka konkretna zmiana zepsuła moją aplikację.

Neville Cook
źródło
5
Wiedziałem o tym, ale wciąż zapominam o tym mniej więcej co 3 miesiące i spędzam kilka godzin na debugowaniu ..
sotn
W moim przypadku testowałem na hoście lokalnym, a parametr „requireSSL” w pliku web.config był ustawiony na „prawda”. Dzięki.
William Pereira
to był mój przypadek i spędziłem zbyt dużo czasu próbując to rozgryźć (miałem czerwonego śledzia z różnymi plikami web.config).
jmoreno
Twoja powyższa sugestia nadal pomaga w 2018 roku. To jest najczęstszy scenariusz. Dzięki!
Vijay Bansal
5

W moim przypadku zorientowałem się, że plik cookie sesji ma domenę zawierającą www.prefiks, podczas gdy żądałem strony bez www..
Dodanie www.do adresu URL natychmiast rozwiązało problem. Później zmieniłem domenę ciasteczka na .mysite.comzamiast www.mysite.com.

Kniganapolke
źródło
5

mój problem polegał na tym, że mieliśmy ten zestaw w web.config

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

oznacza to, że podczas debugowania bez SSL (ustawienie domyślne), plik cookie uwierzytelniania nie zostałby odesłany z powrotem na serwer. oznaczałoby to, że serwer wysyłałby nowy plik cookie uwierzytelniania (z nową sesją) dla każdego żądania z powrotem do klienta.

poprawką jest ustawienie requiressl na false w web.config i true w web.release.config lub włączenie SSL podczas debugowania:

włącz SSL

Josh
źródło
Czym różni się to od odpowiedzi Neville'a Cooka z 2011 roku?
Ian Kemp
4

Korzystając z odpowiedzi Neville'a (usuwanie requireSSL = true w web.config) i nieznacznie modyfikując kod Joela Ethertona, oto kod, który powinien obsługiwać witrynę działającą zarówno w trybie SSL, jak i bez SSL, w zależności od użytkownika i strony (ja wskakuję z powrotem do kodu i nie testowałem go jeszcze na SSL, ale spodziewaj się, że to powinno działać - będę zbyt zajęty później, aby wrócić do tego, więc oto jest:

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;
                }
            }
        }
Reid
źródło
2

Inną możliwością, która powoduje zmianę SessionID między żądaniami, nawet jeśli zdefiniowano Session_OnStart i / lub Session została zainicjowana, jest to, że nazwa hosta adresu URL zawiera nieprawidłowy znak (taki jak podkreślenie). Wydaje mi się, że jest to specyficzne dla IE (niezweryfikowane), ale jeśli Twój adres URL to np.http://server_name/app , to IE zablokuje wszystkie pliki cookie, a informacje o sesji nie będą dostępne między żądaniami.

W rzeczywistości każde żądanie uruchamia oddzielną sesję na serwerze, więc jeśli strona zawiera wiele obrazów, tagów skryptów itp., To każde z tych żądań GET spowoduje inną sesję na serwerze.

Więcej informacji: http://support.microsoft.com/kb/316112

R. Aaron Zupancic
źródło
2

W moim przypadku działo się to często w moich środowiskach programistycznych i testowych. Po wypróbowaniu wszystkich powyższych rozwiązań bez powodzenia stwierdziłem, że udało mi się rozwiązać ten problem, usuwając wszystkie sesyjne pliki cookie. Rozszerzenie dla programistów internetowych sprawia, że ​​jest to bardzo łatwe. Przeważnie używam Firefoksa do testowania i programowania, ale zdarzyło się to również podczas testowania w Chrome. Poprawka działała również w Chrome.

Nie musiałem tego jeszcze robić w środowisku produkcyjnym i nie otrzymałem żadnych zgłoszeń osób, które nie mogą się zalogować. Wydawało się, że dzieje się to dopiero po zabezpieczeniu plików cookie sesji. To się nigdy nie zdarzyło w przeszłości, kiedy nie byli bezpieczni.

Matt L.
źródło
Aktualizacja: zaczęło się to dziać dopiero po zmianie pliku cookie sesji, aby był bezpieczny. Ustaliłem, że dokładny problem jest spowodowany tym, że w przeglądarce znajdują się dwa lub więcej plików cookie sesji o tej samej ścieżce i domenie. Ten, który zawsze był problemem, miał wartość pustą lub zerową. Po usunięciu tego konkretnego pliku cookie problem został rozwiązany. Dodałem również kod w metodzie Global.asax.cs Sessin_Start, aby sprawdzić ten pusty plik cookie, a jeśli tak, ustawić jego datę wygaśnięcia na coś z przeszłości.
Matt L
2

w moim przypadku to dlatego, że modyfikowałem sesję po przekierowaniu z bramki w zewnętrznej aplikacji , więc ponieważ zamiast tego używałem adresu IP na lokalnym hoście w tym adresie URL strony, w rzeczywistości była to inna witryna z różnymi sesjami.

W podsumowaniu

zwróć większą uwagę, jeśli debugujesz aplikację hostowaną w IIS zamiast IIS express i mieszasz swój komputer http: // Ip i http: // localhost na różnych stronach

Iman
źródło
1

Mój problem dotyczył aplikacji Microsoft MediaRoom IPTV. Okazuje się, że aplikacje MPF MRML nie obsługują plików cookie; zmiana na sesje bez plików cookie w pliku web.config rozwiązała mój problem

<sessionState cookieless="true"  />

Oto NAPRAWDĘ stary artykuł na ten temat: ASP.NET bez plików cookie

denvercoder9
źródło
1

Jestem na .NET Core 2.1 i dobrze wiem, że nie chodzi o Core. Brakuje jednak internetu, a Google sprowadził mnie tutaj, więc mam nadzieję, że zaoszczędzę komuś kilka godzin.


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

Zauważ, że zapisywanie i odczytywanie sesji działa, ale wydaje się, że żadne pliki cookie nie są przesyłane do przeglądarki. Przynajmniej nie mogłem nigdzie znaleźć nagłówka „Set-Cookie”.

krivar
źródło
0

Upewnij się, że nie masz bardzo krótkiego limitu czasu sesji, a także upewnij się, że jeśli korzystasz z sesji opartych na plikach cookie, akceptujesz sesję.

Pasek narzędzi FireFox webDeveloperToolbar jest pomocny w takich sytuacjach, ponieważ możesz zobaczyć pliki cookie ustawione dla Twojej aplikacji.

Mitchel Sellers
źródło
2
Domyślam się, że mój limit czasu sesji nie jest ustawiony poniżej jednej sekundy. Zmienia się z każdym szybkim naciśnięciem klawisza F5.
Seb Nilsson
0

Resetowanie identyfikatora sesji może mieć wiele przyczyn. Jednak żaden z wymienionych powyżej nie dotyczy mojego problemu. Więc opiszę to na przyszłość.

W moim przypadku nowa sesja tworzona na każde żądanie skutkowała nieskończoną pętlą przekierowań. Akcja przekierowania odbywa się w zdarzeniu OnActionExecuting .

Czyściłem również wszystkie nagłówki http (także w zdarzeniu OnActionExecuting przy użyciu Response. metody ), aby zapobiec buforowaniu witryn po stronie klienta. Ale ta metoda usuwa wszystkie nagłówki, w tym informacje o sesji użytkownika, a co za tym idzie wszystkie dane z magazynu tymczasowego (którego użyłem później w programie). Więc nawet ustawienie nowej sesji w zdarzeniu Session_Start nie pomogło.

Aby rozwiązać mój problem, upewniłem się, że nie usuwam nagłówków, gdy nastąpi przekierowanie.

Mam nadzieję, że to komuś pomoże.

user3253726
źródło
0

Wpadłem na ten problem w inny sposób. Kontrolery, które miały ten atrybut [SessionState(SessionStateBehavior.ReadOnly)], odczytywały z innej sesji, mimo że ustawiłem wartość w oryginalnej sesji podczas uruchamiania aplikacji. Dodawałem wartość sesji przez _layout.cshtml (może nie najlepszy pomysł?)

Najwyraźniej przyczyną problemu był ReadOnly, ponieważ po usunięciu atrybutu oryginalna sesja (i SessionId) pozostały niezmienione. Użycie rozwiązania Claudio / Microsoft naprawiło to.

goku_da_master
źródło