FormsAuthentication.SignOut (), kullanıcının oturumunu kapatmaz


143

Biraz fazla buna karşı başımı parçaladım. Bir kullanıcının FormsAuthentication.SignOut kullanarak oturumu kapatıldıktan sonra bir sitenin sayfalarına göz atmasını nasıl önleyebilirim? Bunu yapmak için beklenir:

FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();

Ama öyle değil. Doğrudan bir URL yazarsam, yine de sayfaya göz atabilirim. Bir süredir kendi güvenliğinizi kullanmadım, bu yüzden neden işe yaramadığını unutuyorum.


Bu kod olduğu gibi ... tarayıcıda geri tıklandığında sunucudaki sayfayı tekrar ziyaret etmez, sadece sayfanın yerel önbelleğe alınmış sürümünü yeniden yükler. Aşağıdaki tüm çözümler bu gerçeği görmezden geliyor ve aslında burada yaptığınızdan daha fazlasını yapmıyor. Kısacası ... bugüne kadar önbelleğe bakarak kullanıcı çözecek bu soruya cevap yok diyerek önbellek temizlemek için bir yol olduğuna inanmıyorum ... js veya bir sunucu tarafı talimat.
Savaş

Bu yanıt, özellikle de siteniz PEN testlerinde başarısız olursa, kontrol etmek için bazı yollar sunar: stackoverflow.com/questions/31565632/…
Tyler S. Loeper

Yanıtlar:


211

Aradığınızda çerezler temizlenmediğinden FormsAuthentication.SignOut()ve her yeni istekte kimlik doğrulaması yapıldığından kullanıcılar web sitenize göz atabilir . MS belgelerinde çerez temizlenir ama diyor değil mi, hata? Aynı Session.Abandon()şey, çerez hala orada.

Kodunuzu şu şekilde değiştirmeniz gerekir:

FormsAuthentication.SignOut();
Session.Abandon();

// clear authentication cookie
HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie1.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie1);

// clear session cookie (not necessary for your current problem but i would recommend you do it anyway)
SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState");
HttpCookie cookie2 = new HttpCookie(sessionStateSection.CookieName, "");
cookie2.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie2);

FormsAuthentication.RedirectToLoginPage();

HttpCookieiçindedir System.Webad. MSDN Başvurusu .


18
Bu benim için çalışıyor. Ancak, Alan adı özelliği oturum açarken FormsAuthentication çerezinde ayarlanmışsa, oturumu kapattığınızda çerezi geçerken sonlandırırken de ayarlanması gerektiğini belirtmek gerekir
Phil Hale

8
Ayrıca cookie1.HttpOnly = true;
Dmitry Zaets

6
Bu benim için daha iyi bir çözüm gibi görünüyor: Response.Cookies [FormsAuthentication.FormsCookieName] .Expires = DateTime.Now.AddDays (-1);
Randy H.

7
@RandyH. Mevcut FormsAuthentication çerezini yeni bir boş çerezle geçersiz kılmak, istemci sistem saatini geri sarsa bile, çerezden herhangi bir kullanıcı verisi alamayacaklarını garanti eder.
Tri Q Tran

9
Birisi tüm bu yorumları cevapta birleştirebilir mi?
David

22

X64igor ve Phil Haselden'in yukarıdaki gönderilerinden ikisini kullanarak bunu çözdüler:

1. x64igor Oturumu Kapatmak için örnek verdi:

  • İlk önce Oturumu Kapatma Yanıtındaki boş çerezleri geri vererek Kimlik Doğrulama Çerezi ve Oturum Çerezi'ni temizlemeniz gerekir.

    public ActionResult LogOff()
    {
        FormsAuthentication.SignOut();
        Session.Clear();  // This may not be needed -- but can't hurt
        Session.Abandon();
    
        // Clear authentication cookie
        HttpCookie rFormsCookie = new HttpCookie( FormsAuthentication.FormsCookieName, "" );
        rFormsCookie.Expires = DateTime.Now.AddYears( -1 );
        Response.Cookies.Add( rFormsCookie );
    
        // Clear session cookie 
        HttpCookie rSessionCookie = new HttpCookie( "ASP.NET_SessionId", "" );
        rSessionCookie.Expires = DateTime.Now.AddYears( -1 );
        Response.Cookies.Add( rSessionCookie );
    

2. Phil Haselden, oturumdan sonra önbelleğe almanın nasıl önleneceğine dair yukarıdaki örneği verdi:

  • Yanıt yoluyla İstemci Tarafındaki Önbelleği Geçersiz Kılmanız gerekir .

        // Invalidate the Cache on the Client Side
        Response.Cache.SetCacheability( HttpCacheability.NoCache );
        Response.Cache.SetNoStore();
    
        // Redirect to the Home Page (that should be intercepted and redirected to the Login Page first)
        return RedirectToAction( "Index", "Home" ); 
    }
    

1
Bu sorunu çözmek için bütün gün işte boşa. Oturumu kapattıktan sonra denetleyicide yanlış eylemi çağırmaya başladı (Oturum Kapatma değil). Teşekkür ederim, bu sorunu çözdü. Geliştirme ortamı: ASP.NET 4.51 MVC 5.1
Ako

1
İyi cevap! Mütevazi öneri: Kullanım forma takas oturumu çerezleri için x64igor kullandı: SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState"); HttpCookie sessionCookie = new HttpCookie(sessionStateSection.CookieName, "");. Genel olarak, oturum çerezi adı değildir "ASP.NET_SessionId".
seebiscuit

20

Web.config yetkilendirme bölümünüzün içinde doğru şekilde ayarlanmamış gibi geliyor. Örnek için aşağıya bakın.

<authentication mode="Forms">
  <forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
  <deny users="?" />
</authorization>

Bu çok daha basit bir çözüm, bunu bir cevap olarak işaretlerdim. Biri farklı sunucular üzerinde çalışan kodun bir sürümünü var gibi burada ve diğer eklediğiniz ek özellikler ayarlamak gerek yoktu. Bu nedenle, kodu değiştirmek doğru bir çözüm olmamalıdır, yapılandırmayı değiştirmek daha iyidir.
Vladimir Bozic

Varsayılan olarak slidingExpiration, true değerine ayarlanır ( msdn.microsoft.com/library/1d3t3c61(v=vs.100).aspx ). Ve bu nihayet çerezin zaman aşımına ayarlandığı şekilde x dakika sonra geçersiz olmasına neden olur ve kullanıcı SignOut () aracılığıyla oturumu kapattığında değil. Böylece bu, FormsAuthentication kullanarak bir kullanıcının oturumunu kapatmak için istenen davranışla sonuçlanmaz. Yanlışım varsa lütfen düzelt.
OlafW

12

Buradaki anahtar, "Doğrudan bir URL yazarsam ..." demenizdir.

Varsayılan olarak form kimlik doğrulaması altında tarayıcı, sayfaları kullanıcı için önbelleğe alır. Bu nedenle, doğrudan tarayıcıların adres kutusu açılır listesinden bir URL seçerek veya içine yazarak, sayfayı tarayıcının önbelleğinden alabilir ve kimlik doğrulama / yetkilendirmeyi kontrol etmek için hiçbir zaman sunucuya geri dönmeyebilir. Bunun çözümü, her sayfanın Page_Load olayında veya temel sayfanızın OnLoad () öğesinde istemci tarafı önbelleğe almayı önlemektir:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Ayrıca şunları da arayabilirsiniz:

Response.Cache.SetNoStore();

11

Daha önce de bununla mücadele ettim.

İşte olup bitenler için bir benzetme ... Yeni bir ziyaretçi, Joe, siteye geliyor ve giriş sayfası üzerinden FormsAuthentication kullanarak giriş yapıyor. ASP.NET, Joe için yeni bir kimlik oluşturur ve ona bir çerez verir. Bu kurabiye evin anahtarı gibidir ve Joe bu anahtarla döndüğü sürece kilidi açabilir. Her ziyaretçiye yeni bir anahtar ve yeni bir kilit verilir.

Arandığında FormsAuthentication.SignOut(), sistem Joe'ya anahtarı kaybetmesini söyler. Normalde, bu işe yarıyor, Joe artık anahtara sahip olmadığı için içeri giremiyor.

Joe hiç geri gelir ve Ancak, does o kayıp anahtara sahip, o geri let olduğunu!

Söyleyebileceğim kadarıyla, ASP.NET'e kapının kilidini değiştirmesini söylemenin bir yolu yok!

Bununla nasıl yaşayabileceğim, Joe'nun adını bir Oturum değişkeninde hatırlamaktır. Oturumu kapattığında, artık oturumdan vazgeçmediğim için Oturumu terk ediyorum. Daha sonra, izin verilip verilmediğini kontrol etmek için sadece kimliğini karşılaştırıyorum.Adı mevcut oturumun sahip olduğu şeyle karşılaştırıyorum ve eşleşmezlerse geçerli bir ziyaretçi değil.

Kısacası, bir web sitesi için, User.Identity.IsAuthenticatedOturum değişkenlerinizi de kontrol etmeden güvenmeyin !


8
+ 1, buna 'Çerez tekrar saldırısı' denir. FormsAuthentication.SignOut'un sınırlamaları hakkında bir makale var: support.microsoft.com/kb/900111
Dmitry

3
Yukarıdaki bağlantıyı takip etmek isteyen herkes için öldü. Bu sayfanın bir kopyasını almak için WaybackMachine'ı kullanmayı deneyebilirsiniz, ancak HEMEN kullanıcıyı yeniden yönlendirmeye çalışır. web.archive.org/web/20171128133421/https://…
killa-byte

7

Birçok aramadan sonra nihayet bu benim için çalıştı. Umut ediyorum bu yardım eder.

public ActionResult LogOff()
{
    AuthenticationManager.SignOut();
    HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
    return RedirectToAction("Index", "Home");
}

<li class="page-scroll">@Html.ActionLink("Log off", "LogOff", "Account")</li>

PHP'de yıllardır web uygulamaları geliştiriyorum. Bu yüzden MVC'de yeniyim ... İtiraf ediyorum, ama kimin oturumunu kapatmak kadar basit bir şey düşünen kimin çok zor olacağını itiraf ediyorum? Bu sayfadaki diğer tüm komut dosyalarını satırdan denedim ve bu işe yarayan tek şeydi. Gönderdiğiniz için teşekkürler!
Anthony Griggs

6

Bu benim için çalışıyor

public virtual ActionResult LogOff()
    {
        FormsAuthentication.SignOut();
        foreach (var cookie in Request.Cookies.AllKeys)
        {
            Request.Cookies.Remove(cookie);
        }
        foreach (var cookie in Response.Cookies.AllKeys)
        {
            Response.Cookies.Remove(cookie);
        }
        return RedirectToAction(MVC.Home.Index());
    }

3

Gönderdiğiniz kod, form kimlik doğrulama jetonunu doğru şekilde kaldırması gerektiği gibi görünüyor, bu nedenle söz konusu klasörlerin / sayfaların gerçekten korunmaması mümkündür.

Giriş yapılmadan önce sayfalara erişilemediğini onayladınız mı?

Kullandığınız web.config ayarlarını ve oturum açma kodunu gönderebilir misiniz?


3

Tüm Sayfalarım için bir temel sınıf yazıyorum ve aynı sayıya geldim. Aşağıdaki gibi kod vardı ve işe yaramadı. İzleyerek, denetim RedirectToLoginPage () deyiminden yeniden yönlendirilmeden bir sonraki satıra geçer.

if (_requiresAuthentication)
{
    if (!User.Identity.IsAuthenticated)
        FormsAuthentication.RedirectToLoginPage();

    // check authorization for restricted pages only
    if (_isRestrictedPage) AuthorizePageAndButtons();
}

İki çözüm olduğunu öğrendim. FormsAuthentication.RedirectToLoginPage (); olmak

if (!User.Identity.IsAuthenticated)
    Response.Redirect(FormsAuthentication.LoginUrl);

VEYA web.config dosyasını ekleyerek değiştirmek için

<authorization>
  <deny users="?" />
</authorization>

İkinci durumda, izleme sırasında kontrol istenen sayfaya ulaşmadı. Kırılma noktasına ulaşmadan hemen önce giriş URL'sine yönlendirilir. Bu nedenle, SignOut () yöntemi sorun değil, yönlendirme yöntemi budur.

Umarım bu birine yardımcı olabilir

Saygılarımızla


2
Ayrıca sadece FormsAuthentication.RedirectToLoginPage () çağrıldıktan sonra) Response.End (diyebiliriz
murki

Bence MS konusunda biraz yanlış iletişim var. Kullanıcıların giriş sayfasına dönmelerini istiyorsanız kilitlemeniz gerekir. Aksi takdirde çerçeve erişime izin verir. Yani bu yazıda # 2 numaralı çözümü söylemelisiniz.
Josh Robinson

3

Buradaki bazı önerileri denedim ve tarayıcı geri düğmesini kullanabildiğim sırada, bir menü seçimine tıkladığımda [ActionResult] için [Yetkilendir] belirteci beni doğrudan giriş ekranına geri gönderdi.

İşte çıkış kodum:

        FormsAuthentication.SignOut();
        Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
        Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
        HttpCookie cookie = HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (cookie != null)
        {
            cookie.Expires = DateTime.Now.AddDays(-1);
            Response.Cookies.Add(cookie);
        }

Her ne kadar tarayıcıda geri işlevi beni geri aldı ve güvenli menü (hala üzerinde çalışıyorum) görüntülenmesine rağmen ben app güvenli bir şey yapamadı.

Bu yardımcı olur umarım


Teşekkürler. Bu benim için çalışan çözüm ( <deny users="?" />web.config içinde gerek yok )
Alexei

3

Bu konudaki cevapların çoğunu denedim, şans yok. Bunun sonu:

protected void btnLogout_Click(object sender, EventArgs e)
{
    FormsAuthentication.Initialize();
    var fat = new FormsAuthenticationTicket(1, "", DateTime.Now, DateTime.Now.AddMinutes(-30), false, string.Empty, FormsAuthentication.FormsCookiePath);
    Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(fat)));
    FormsAuthentication.RedirectToLoginPage();
}

Burada buldum : http://forums.asp.net/t/1306526.aspx/1


3

Bu Yanıt teknik olarak Khosro.Pakmanesh ile aynıdır. Cevabının bu konudaki diğer cevaplardan nasıl farklı olduğunu ve hangi kullanım durumunda kullanılabileceğini açıklığa kavuşturmak için gönderiyorum.

Genel olarak bir kullanıcı oturumunu temizlemek,

HttpContext.Session.Abandon();
FormsAuthentication.SignOut();

kullanıcının oturumunu etkin bir şekilde kapatır. Bununla birlikte , aynı İstekte kontrol etmeniz gerekiyorsa Request.isAuthenticated(örneğin, bir Yetkilendirme Filtresinde sıklıkla olabileceği gibi),

Request.isAuthenticated == true

hatta yaptıktan sonra HttpContext.Session.Abandon()ve FormsAuthentication.SignOut().

İşe yarayan tek şey yapmaktı

AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);

Bu etkili bir şekilde ayarlanır Request.isAuthenticated = false.


2

Bu benim ayarladığınızda bana oluyor başladı doğrulama> formlar> Yol özelliğini de Web.config. Bunu kaldırmak sorunu çözdü ve basit bir FormsAuthentication.SignOut();çerez tekrar kaldırıldı.


1

Bir alt etki alanından (sub1.etkialanı.com) oturum açıp farklı bir alt etki alanından (www.etkialanı.com) oturumu kapatmaya çalışmanız olabilir.


1

Ben sadece aynı sorun vardı, burada SignOut () görünüşe göre bilet kaldırmak için başarısız oldu. Ancak yalnızca belirli bir durumda, başka bir mantığın yönlendirmeye neden olduğu. Bu ikinci yönlendirmeyi kaldırdıktan sonra (bir hata iletisiyle değiştirdim), sorun ortadan kalktı.

Sorun, sayfanın yanlış zamanda yeniden yönlendirilmiş olması ve dolayısıyla kimlik doğrulamasını tetiklememesi olmalıdır.


1

Şimdi benzer bir sorun yaşıyorum ve orijinal posterin yanı sıra benim durumumdaki sorunun yeniden yönlendirmeden kaynaklandığına inanıyorum. Varsayılan olarak Response.Redirect, yakalanana ve yeniden yönlendirme hemen yürütülene kadar hemen kabarcıklı bir özel duruma neden olur, bunun değiştirilmiş çerez koleksiyonunun istemciye aktarılmasını önlediğini tahmin ediyorum. Kodunuzu kullanmak için değiştirirseniz:

Response.Redirect("url", false);

Bu, istisnayı önler ve çerezin istemciye düzgün bir şekilde geri gönderilmesine izin veriyor gibi görünür.


1

Oturum aç düğmesine bastığınızda bir oturum değişkeni göndermeye çalışın. Karşılama sayfasında, ilk önce bu oturumun sayfa yüklemesinde veya Init Event'de boş olup olmadığını kontrol edin:

if(Session["UserID"] == null || Session["UserID"] == "")
{
    Response.Redirect("Login.aspx");
}

1

Benim için aşağıdaki yaklaşım işe yarıyor. "FormsAuthentication.SignOut ()" deyiminden sonra herhangi bir hata varsa, SingOut çalışmadığını düşünüyorum.

public ActionResult SignOut()
    {
        if (Request.IsAuthenticated)
        {
            FormsAuthentication.SignOut();

            return Redirect("~/");
        }
        return View();
     }

0

IE kullanarak bu davranışı test ediyor / görüyor musunuz? IE bu sayfaları önbellekten yayınlıyor olabilir. IE'nin önbelleğini temizlemesini sağlamak çok zordur ve bu nedenle birçok durumda, oturumu kapattıktan sonra bile, "güvenli" sayfalardan birinin URL'sini yazmak önbelleğe alınmış içeriği daha önce gösterir.

(Farklı bir kullanıcı olarak giriş yaptığınızda bile bu davranışı gördüm ve IE, sayfanızın üstünde eski kullanıcının kullanıcı adıyla "Hoş Geldiniz" çubuğunu gösterir. Günümüzde genellikle yeniden yükleme bunu günceller, ancak kalıcıysa , yine de önbellek sorunu olabilir.)


0

Session.abandon () yapmak ve çerezi yok etmek oldukça iyi çalışıyor. Mvc3 kullanıyorum ve korunan bir sayfaya gidip oturumu kapatırsanız ve tarayıcı geçmişinizden geçerseniz sorun oluşuyor gibi görünüyor. Büyük bir anlaşma değil ama yine de sinir bozucu.

Web uygulamamda bağlantılar arasında gezinmeye çalışmak doğru şekilde çalışıyor.

Tarayıcı önbelleğe almamaya ayarlamak, gidilecek yol olabilir.


0

MVC için bu benim için çalışıyor:

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();
            return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
        }

0

Sorunu anlamamıza yardımcı olacak bazı bilgiler eklemek istedim. Form Kimlik Doğrulaması, kullanıcı verilerinin bir çerezde veya URL'nin sorgu dizesinde depolanmasına izin verir. Sitenizin desteklediği yöntem web.config dosyasında yapılandırılabilir.

Microsoft'a göre :

SignOut yöntemi, CookiesSupported yanlışsa form kimlik doğrulaması bilet bilgilerini çerezden veya URL'den kaldırır .

Aynı zamanda derler ki :

Uygulamanın cookieless form kimlik doğrulaması için yapılandırılıp yapılandırılmadığını gösteren HttpCookieMode değerlerinden biri. Varsayılan UseDeviceProfile olduğunu .

Son olarak, UseDeviceProfile ile ilgili olarak şunları söylüyorlar :

CookieMode özelliği UseDeviceProfile olarak ayarlanırsa , geçerli İstek için Tarayıcı hem çerezleri hem de çerezlerle yeniden yönlendirmeyi destekliyorsa , CookiesSupported özelliği true değerini döndürür ; aksi halde, CookiesSupported özelliği false değerini döndürür.

Kullanıcının tarayıcısına bağlı olarak, bunları bir araya getirerek varsayılan yapılandırma CookiesSupported'ın true olmasına neden olabilir , bu da SignOut yönteminin bileti çerezden temizlemediği anlamına gelir. Bu sezgisel gibi görünüyor ve neden bu şekilde çalıştığını bilmiyorum - SignOut'un hiçbir koşulda kullanıcıyı kapatmasını beklerim.

SignOut'u kendi başına çalıştırmanın bir yolu, çerez modunu web.config dosyasında "UseCookies" (yani çerezler gereklidir) olarak değiştirmektir:

<authentication mode="Forms">
  <forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>

Testlerime göre, bunu yapmak SignOut'u sitenizin maliyetiyle tek başına çalıştırıyor, şimdi çerezlerin düzgün çalışması gerekiyor.


Bence bunu yanlış okuyorsun. SignOut () ile ilgili olarak, CookiesSupported yanlışsa, aksi takdirde çerezden URL'den silineceği anlamına geldiklerinden eminim. Yani, "SignOut yöntemi form kimlik doğrulama bileti bilgilerini çerezden veya CookiesSupported yanlışsa URL'den kaldırır" yazmış olmalıdır.
Oskar Berggren

-1

WIF unutmayın reddeder STS gelen wsignoutcleanup mesajı ııS'DEN uygulamanın adı ile url eşleşmezse temizleme için çerezler tarayıcı anlatmak için, ben ortalama DURUM HASSAS . WIF yeşil ok Çek ile yanıt verir, ancak olacak değil tarayıcıya silme çerezleri için komut göndermek.

Bu nedenle, URL'lerinizin büyük / küçük harf duyarlılığına dikkat etmeniz gerekir.

Örneğin, ThinkTecture Identity Server, ziyaret eden RP'lerin URL'lerini tek bir çerezde kaydeder, ancak hepsini küçük harf yapar. WIF, wsignoutcleanup iletisini küçük harfle alır ve IIS'deki uygulama adıyla karşılaştırır. Eşleşmezse, çerezleri silmez, ancak tarayıcıya Tamam bildirir. Bu nedenle, bu Kimlik Sunucusu için, bu tür sorunları önlemek için web.config içindeki tüm URL'leri ve IIS'deki tüm uygulama adlarını küçük harflerle yazmam gerekiyordu.

Ayrıca, STS alt etki alanı dışında uygulamalarınız varsa, üçüncü taraf çerezlerine tarayıcıda izin vermeyi unutmayın, aksi takdirde WIF bunu söylemiş olsa bile tarayıcı çerezleri silmez.


1
WIF? STS? ThinkTecture Kimlik Sunucusu? Tüm bunlar nedir ve bu soru ile nasıl ilişkilidir?
Oskar Berggren
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.