Domanda

Mi sono rotto la testa un po 'troppo a lungo. Come posso impedire a un utente di sfogliare le pagine di un sito dopo che sono stati disconnessi utilizzando FormsAuthentication.SignOut? Mi aspetto che questo lo faccia:

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

Ma non lo fa. Se scrivo direttamente un URL, posso comunque accedere alla pagina. Non uso la sicurezza roll-your-own da un po ', quindi dimentico perché non funziona.

È stato utile?

Soluzione

Gli utenti possono comunque navigare nel tuo sito Web perché i cookie non vengono cancellati quando chiami FormsAuthentication.SignOut () e vengono autenticati su ogni nuova richiesta. Nella documentazione MS si dice che i cookie verranno cancellati ma non lo fanno, bug? È esattamente lo stesso con Session.Abandon () , il cookie è ancora lì.

Dovresti cambiare il tuo codice in questo:

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

HttpCookie si trova nello spazio dei nomi System.Web . Riferimento MSDN .

Altri suggerimenti

Mi sembra che tu non abbia la sezione di autorizzazione web.config impostata correttamente. Vedi sotto per un esempio.

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

L'utilizzo di due dei precedenti post di x64igor e Phil Haselden ha risolto questo problema:

1. x64igor ha fornito l'esempio per eseguire il logout:

  • Devi prima cancellare il cookie di autenticazione e il cookie di sessione restituendo i cookie vuoti nella risposta al logout.

    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 ha fornito l'esempio sopra di come prevenire la memorizzazione nella cache dopo il logout:

  • Devi invalidare la cache sul lato client tramite la risposta .

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

La chiave qui è che dici " Se scrivo direttamente un URL ... " ;.

Per impostazione predefinita, sotto l'autenticazione basata su moduli, il browser memorizza nella cache le pagine per l'utente. Quindi, selezionando un URL direttamente dal menu a discesa della casella dell'indirizzo del browser o digitandolo, PUO 'ottenere la pagina dalla cache del browser e non tornare mai al server per verificare l'autenticazione / autorizzazione. La soluzione a questo è impedire la memorizzazione nella cache sul lato client nell'evento Page_Load di ogni pagina o in OnLoad () della pagina di base:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Potresti anche chiamare:

Response.Cache.SetNoStore();

Ho già lottato con questo prima.

Ecco un'analogia per quello che sembra succedere ... Un nuovo visitatore, Joe, arriva al sito e accede tramite la pagina di accesso usando FormsAuthentication. ASP.NET genera una nuova identità per Joe e gli fornisce un cookie. Quel biscotto è come la chiave di casa, e finché Joe ritorna con quella chiave, può aprire la serratura. A ogni visitatore viene fornita una nuova chiave e un nuovo lucchetto da utilizzare.

Quando viene chiamato FormsAuthentication.SignOut () , il sistema dice a Joe di perdere la chiave. Normalmente funziona, dato che Joe non ha più la chiave, non può entrare.

Tuttavia, se Joe torna, e ha la chiave persa, viene lasciato rientrare!

Da quello che posso dire, non c'è modo di dire ad ASP.NET di cambiare la serratura della porta!

Il modo in cui posso convivere con questo è ricordare il nome di Joe in una variabile Session. Quando si disconnette, abbandono la Sessione, quindi non ho più il suo nome. Più tardi, per verificare se gli è consentito, ho semplicemente confrontato la sua identità. Nome a quello che ha la sessione corrente e, se non corrispondono, non è un visitatore valido.

In breve, per un sito Web, NON fare affidamento su User.Identity.IsAuthenticated senza controllare anche le variabili di sessione!

Questo funziona per me

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

Dopo molte ricerche finalmente questo ha funzionato per me. Spero che sia d'aiuto.

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>

Il codice che hai pubblicato sembra che dovrebbe rimuovere correttamente il token di autenticazione dei moduli, quindi è possibile che le cartelle / pagine in questione non siano effettivamente protette.

Hai confermato che non è possibile accedere alle pagine prima che si sia verificato un accesso?

Puoi pubblicare le impostazioni web.config e il codice di accesso che stai utilizzando?

Ho scritto una classe di base per tutte le mie pagine e ho riscontrato lo stesso problema. Avevo un codice simile al seguente e non funzionava. Tramite la traccia, il controllo passa dall'istruzione RedirectToLoginPage () alla riga successiva senza essere reindirizzato.

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

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

Ho scoperto che ci sono due soluzioni. O per modificare FormsAuthentication.RedirectToLoginPage (); essere

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

OPPURE per modificare web.config aggiungendo

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

Nel secondo caso, durante la traccia, il controllo non ha raggiunto la pagina richiesta. È stato reindirizzato immediatamente all'URL di accesso prima di colpire il punto di interruzione. Quindi, il metodo SignOut () non è il problema, il metodo di reindirizzamento è quello.

Spero che possa aiutare qualcuno

Saluti

Ho appena provato alcuni dei suggerimenti qui e mentre sono stato in grado di utilizzare il pulsante Indietro del browser, quando ho fatto clic su una selezione di menu il token [Autorizza] per quel [ActionResult] mi ha riportato alla schermata di accesso.

Ecco il mio codice di disconnessione:

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

Anche se la funzione Indietro sul browser mi ha riportato indietro e visualizzato il menu protetto (ci sto ancora lavorando) non sono stato in grado di fare nulla che fosse protetto nell'app.

Spero che questo aiuti

Ho provato la maggior parte delle risposte in questa discussione, senza fortuna. Finito con questo:

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

Trovato qui: http://forums.asp.net/t/1306526. aspx / 1

Questa risposta è tecnicamente identica a Khosro.Pakmanesh. Lo sto postando per chiarire in che modo la sua risposta differisce dalle altre risposte su questa discussione e in quale caso può essere utilizzata.

In generale per cancellare una sessione utente, facendo

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

disconnetterà efficacemente l'utente. Tuttavia , se nella stessa richiesta è necessario selezionare Request.isAuthenticated (come spesso accade in un filtro di autorizzazione, ad esempio), allora troverai che

Request.isAuthenticated == true

anche _dopo aver HttpContext.Session.Abandon () e FormsAuthentication.SignOut () .

L'unica cosa che ha funzionato è stata fare

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

Ciò imposta effettivamente Request.isAuthenticated = false .

Questo ha cominciato a succedere a me quando ho impostato l'autenticazione > forme > Proprietà percorso in Web.config . La rimozione risolveva il problema e un semplice FormsAuthentication.SignOut (); rimuoveva nuovamente il cookie.

È possibile che tu stia effettuando l'accesso da un sottodominio (sub1.domain.com) e quindi provando a disconnettersi da un altro sottodominio (www.domain.com).

Ho appena avuto lo stesso problema, in cui SignOut () apparentemente non è riuscito a rimuovere correttamente il ticket. Ma solo in un caso specifico, in cui un'altra logica ha causato un reindirizzamento. Dopo aver rimosso questo secondo reindirizzamento (sostituito con un messaggio di errore), il problema è scomparso.

Il problema deve essere stato che la pagina è stata reindirizzata nel momento sbagliato, quindi non ha innescato l'autenticazione.

Ora sto riscontrando un problema simile e credo che il problema nel mio caso, così come il poster originale, sia dovuto al reindirizzamento. Per impostazione predefinita, un Response.Redirect provoca un'eccezione che bolle immediatamente fino a quando non viene rilevato e il reindirizzamento viene immediatamente eseguito, suppongo che ciò impedisca il trasferimento della raccolta di cookie modificata al client. Se modifichi il codice per utilizzarlo:

Response.Redirect("url", false);

Ciò impedisce l'eccezione e sembra consentire il corretto invio del cookie al client.

Prova a inviare una variabile di sessione quando premi Accedi. E nella pagina di benvenuto, controlla innanzitutto se quella sessione è vuota in questo modo nel caricamento della pagina o nell'evento Init:

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

Per me, il seguente approccio funziona. Penso che se ci sono errori dopo il "quots FormsAuthentication.SignOut ()" dichiarazione, SingOut non funziona.

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

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

Stai testando / vedendo questo comportamento usando IE? È possibile che IE stia offrendo quelle pagine dalla cache. È notoriamente difficile convincere IE a svuotare la sua cache, e quindi in molte occasioni, anche dopo esserti disconnesso, digitando l'URL di uno dei "protetti". le pagine mostrerebbero il contenuto memorizzato nella cache di prima.

(Ho visto questo comportamento anche quando si accede come un altro utente e IE mostra la barra "Benvenuto" nella parte superiore della pagina, con il nome utente dell'utente precedente. Oggi, di solito un ricaricamento lo aggiornerà , ma se è persistente, potrebbe comunque essere un problema di memorizzazione nella cache.)

Fare Session.abandon () e distruggere il cookie funziona piuttosto bene. Sto usando mvc3 e sembra che il problema si verifichi se vai su una pagina protetta, esci e vai nella cronologia del tuo browser. Non è un grosso problema ma è comunque un po 'fastidioso.

Cercare di scorrere i collegamenti sulla mia app Web funziona comunque nel modo giusto.

L'impostazione per non eseguire la memorizzazione nella cache del browser potrebbe essere la strada da percorrere.

Per MVC questo funziona per me:

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

Volevo aggiungere alcune informazioni per aiutare a capire il problema. L'autenticazione basata su moduli consente di archiviare i dati dell'utente in un cookie o nella stringa di query dell'URL. Il metodo supportato dal tuo sito può essere configurato nel file web.config.

Secondo a Microsoft :

  

Il metodo SignOut rimuove le informazioni sul ticket di autenticazione dei moduli   dal cookie o dall'URL se Cookie supportato è falso .

Allo stesso tempo, dicono :

  

Uno dei valori di HttpCookieMode che indica se il   l'applicazione è configurata per l'autenticazione di moduli senza cookie. Il    predefinito è UseDeviceProfile .

Infine, per quanto riguarda UseDeviceProfile, dicono :

  

Se la proprietà CookieMode è impostata su UseDeviceProfile, il file    Cookie La proprietà supportata restituirà true se il browser per    La richiesta corrente supporta entrambi i cookie e il reindirizzamento con i cookie ;   in caso contrario, la proprietà CookiesSupported restituirà false.

Mettendo tutto insieme, a seconda del browser dell'utente, la configurazione predefinita potrebbe comportare che Cookie supportati sia vero , il che significa che il metodo SignOut non cancella il ticket dal cookie. Questo sembra controintuitivo e non so perché funzioni in questo modo - mi aspetto che SignOut disconnetta l'utente in qualsiasi circostanza.

Un modo per far funzionare SignOut da solo è cambiare la modalità cookie in " UseCookies " (vale a dire che sono richiesti i cookie) nel file web.config:

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

Secondo i miei test, facendo questo SignOut funziona da solo a spese del tuo sito ora richiedendo i cookie per funzionare correttamente.

Tieni presente che WIF rifiuta di dire al browser di ripulire i cookie se il messaggio wsignoutcleanup di STS non corrisponde all'URL con il nome dell'applicazione di IIS e intendo CASE SENSITIVE . WIF risponde con il segno di spunta verde OK, ma non invierà il comando per eliminare i cookie dal browser.

Quindi, devi prestare attenzione alla distinzione tra maiuscole e minuscole dei tuoi URL.

Ad esempio, ThinkTecture Identity Server salva gli URL dei RP visitanti in un cookie, ma li rende tutti minuscoli. WIF riceverà il messaggio wsignoutcleanup in minuscolo e lo confronterà con il nome dell'applicazione in IIS. Se non corrisponde, non elimina i cookie, ma segnalerà OK al browser. Quindi, per questo Identity Server ho dovuto scrivere tutti gli URL in web.config e tutti i nomi delle applicazioni in IIS in lettere minuscole, al fine di evitare tali problemi.

Inoltre, non dimenticare di consentire i cookie di terze parti nel browser se hai applicazioni al di fuori del sottodominio di STS, altrimenti il ??browser non eliminerà i cookie anche se WIF glielo dice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top