web-dev-qa-db-fra.com

FormsAuthentication.SignOut () ne déconnecte pas l'utilisateur

M'a écrasé la tête un peu trop longtemps. Comment empêcher un utilisateur de parcourir les pages d'un site après sa déconnexion à l'aide de FormsAuthentication.SignOut? Je m'attendrais à ce que cela se produise:

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

Mais ce n'est pas le cas. Si je tape directement une URL, je peux toujours accéder à la page. Je n'ai pas utilisé la sécurité personnelle depuis un moment, alors j'oublie pourquoi cela ne fonctionne pas.

139
Jason

Les utilisateurs peuvent toujours naviguer sur votre site Web, car les cookies ne sont pas effacés lorsque vous appelez FormsAuthentication.SignOut() et ils sont authentifiés à chaque nouvelle demande. Dans la documentation MS, il est indiqué que le cookie sera effacé mais pas, bug? C'est exactement la même chose avec Session.Abandon(), le cookie est toujours là.

Vous devriez changer votre code en ceci:

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 est dans le System.Web espace de noms. référence MSDN .

199
Igor Jerosimić

L'utilisation de deux des publications précédentes de x64igor et Phil Haselden a résolu ce problème:

1. X64igor a donné l'exemple pour faire la déconnexion:

  • Vous devez d’abord effacer le cookie d’authentification et le cookie de session en transmettant des cookies vides dans la réponse à la déconnexion.

    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 a donné l'exemple ci-dessus de la façon d'empêcher la mise en cache après la déconnexion:

  • Vous devez Invalider le cache côté client via la réponse.

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

Il me semble que vous n’avez pas configuré correctement votre section d’autorisation web.config. Voir ci-dessous pour un exemple.

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

La clé ici est que vous dites "Si je tape directement une URL ...".

Par défaut, sous l'authentification par formulaires, le navigateur met en cache les pages de l'utilisateur. Ainsi, en sélectionnant une URL directement dans la liste déroulante des adresses du navigateur, ou en la saisissant, PEUT extraire la page du cache du navigateur et ne jamais revenir sur le serveur pour vérifier l'authentification/autorisation. La solution consiste à empêcher la mise en cache côté client dans l'événement Page_Load de chaque page ou dans le OnLoad () de votre page de base:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Vous pouvez aussi appeler:

Response.Cache.SetNoStore();
12
Phil Haselden

J'ai déjà eu du mal avec ça aussi.

Voici une analogie avec ce qui semble se passer ... Un nouveau visiteur, Joe, vient sur le site et se connecte via la page de connexion à l'aide de FormsAuthentication. ASP.NET génère une nouvelle identité pour Joe et lui transmet un cookie. Ce cookie est comme la clé de la maison, et tant que Joe reviendra avec cette clé, il pourra ouvrir la serrure. Chaque visiteur reçoit une nouvelle clé et un nouveau verrou à utiliser.

Lorsque FormsAuthentication.SignOut() est appelé, le système demande à Joe de perdre la clé. Normalement, cela fonctionne, puisque Joe n'a plus la clé, il ne peut pas entrer.

Cependant, si Joe revient, et a a cette clé perdue, il est laissé entrer!

D'après ce que je peux dire, il n'y a aucun moyen de dire à ASP.NET de changer le verrou de la porte!

Pour vivre avec cela, je me souviens du nom de Joe dans une variable de session. Quand il se déconnecte, j'abandonne la session pour ne plus avoir son nom. Plus tard, pour vérifier s’il est autorisé à entrer, je compare simplement son Identity.Name à ce que la session actuelle a, et s’ils ne correspondent pas, il n’est pas un visiteur valide.

En bref, pour un site Web, ne comptez PAS sur User.Identity.IsAuthenticated sans vérifier également vos variables de session!

11
Glen Little

Ça marche pour moi

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

Après de nombreuses recherches, cela a finalement fonctionné pour moi. J'espère que ça aide.

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>
6
Khosro.Pakmanesh

J'ai écrit un cours de base pour toutes mes pages et je suis arrivé au même problème. J'ai eu le code comme le suivant et cela n'a pas fonctionné. En traçant, le contrôle passe de l'instruction RedirectToLoginPage () à la ligne suivante sans être redirigé.

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

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

J'ai découvert qu'il y a deux solutions. Soit pour modifier FormsAuthentication.RedirectToLoginPage (); être

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

OU pour modifier le fichier web.config en ajoutant

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

Dans le second cas, lors du traçage, le contrôle n’atteignait pas la page demandée. Il a été redirigé immédiatement vers l'URL de connexion avant de frapper le point de rupture. Par conséquent, la méthode SignOut () n'est pas le problème, mais la méthode de redirection.

J'espère que cela peut aider quelqu'un

Cordialement

3
Wahid Shalaly

Cette réponse est techniquement identique à Khosro.Pakmanesh. Je le poste pour clarifier en quoi sa réponse diffère des autres réponses sur ce fil, et dans quel cas d'utilisation elle peut être utilisée.

En général, pour effacer une session utilisateur, faites

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

va effectivement déconnecter l'utilisateur. Cependant, si dans la même demande vous devez vérifier Request.isAuthenticated (Comme cela arrive souvent dans un filtre d'autorisation, par exemple), alors vous constaterez que

Request.isAuthenticated == true

même _après vous avez fait HttpContext.Session.Abandon() et FormsAuthentication.SignOut().

La seule chose qui a fonctionné faisait

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

Cela définit efficacement Request.isAuthenticated = false.

3
seebiscuit

Le code que vous avez posté semble devoir supprimer correctement le jeton d'authentification par formulaire, il est donc possible que les dossiers/pages en question ne soient pas réellement protégés.

Avez-vous confirmé que les pages ne sont pas accessibles avant la connexion?

Pouvez-vous publier les paramètres web.config et le code de connexion que vous utilisez?

3
Abram Simon

Je viens d'essayer certaines des suggestions ici et bien que j'ai pu utiliser le bouton Précédent du navigateur, lorsque j'ai cliqué sur une sélection de menu, le jeton [Autoriser] correspondant à [ActionResult] m'a renvoyé directement à l'écran de connexion.

Voici mon code de déconnexion:

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

Bien que la fonction de retour sur le navigateur me reprenne et affiche le menu sécurisé (je travaille toujours dessus), je ne pouvais rien faire qui soit sécurisé dans l'application.

J'espère que cela t'aides

3
DonH

J'ai essayé la plupart des réponses dans ce fil, pas de chance. Fini avec ceci:

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

Je l'ai trouvé ici: http://forums.asp.net/t/1306526.aspx/1

3
stoffen

Cela a commencé à se produire lorsque j'ai défini la propriété authentication> forms> Path dans Web.config. Supprimer ce problème a résolu le problème et un simple FormsAuthentication.SignOut(); a à nouveau supprimé le cookie.

2
BPM

Il se peut que vous vous connectiez depuis un sous-domaine (sub1.domain.com), puis que vous tentiez de vous déconnecter d'un autre sous-domaine (www.domain.com).

1
jorsh1

Je viens d'avoir le même problème, où SignOut () apparemment n'a pas réussi à supprimer correctement le ticket. Mais seulement dans un cas spécifique, où une autre logique a provoqué une redirection. Après avoir supprimé cette seconde redirection (remplacée par un message d'erreur), le problème a disparu.

Le problème devait être que la page avait été redirigée au mauvais moment, ne déclenchant donc pas l'authentification.

1
Peder Skou

J'ai un problème similaire maintenant et je crois que le problème dans mon cas, ainsi que dans l'affiche originale, est dû à la redirection. Par défaut, Response.Redirect crée une exception qui bouillonne immédiatement jusqu'à ce qu'elle soit capturée et que la redirection soit immédiatement exécutée. Je suppose que cela empêche la collection de cookies modifiée d'être transmise au client. Si vous modifiez votre code pour l'utiliser:

Response.Redirect("url", false);

Cela empêche l'exception et semble permettre au cookie d'être correctement renvoyé au client.

1
lostatredrock

Essayez simplement d’envoyer une variable de session lorsque vous appuyez sur log in. Et sur la page d’accueil, vérifiez d’abord si cette session est vide comme ceci dans le chargement de la page ou dans l’événement Init:

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

Pour moi, l'approche suivante fonctionne. Je pense que s'il y a une erreur après l'instruction "FormsAuthentication.SignOut ()", SingOut ne fonctionne pas.

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

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

Je voulais ajouter des informations pour aider à comprendre le problème. L'authentification par formulaire permet de stocker les données utilisateur dans un cookie ou dans la chaîne de requête de l'URL. La méthode prise en charge par votre site peut être configurée dans le fichier web.config.

selon Microsoft :

La méthode SignOut supprime les informations du ticket d’authentification de formulaires du cookie ou de l’URL si CookiesSupported est false.

Dans le même temps, ils disent :

Une des valeurs HttpCookieMode qui indique si l'application est configurée pour l'authentification par formulaire sans cookie. Le la valeur par défaut est UseDeviceProfile.

Enfin, en ce qui concerne UseDeviceProfile, disent-ils :

Si la propriété CookieMode est définie sur UseDeviceProfile, la propriété CookiesSupported retournera true si le navigateur pour le Current Request prend en charge les cookies et la redirection avec cookies; sinon, la propriété CookiesSupported retournera false.

En combinant tout cela ensemble, en fonction du navigateur de l'utilisateur, la configuration par défaut peut donner comme résultat CookiesSupported true , ce qui signifie que la méthode SignOut n'efface pas le ticket. du cookie. Cela semble contre-intuitif et je ne sais pas pourquoi cela fonctionne de cette façon. Je m'attendrais à ce que SignOut déconnecte l'utilisateur de toutes les circonstances.

Une façon de faire en sorte que SignOut fonctionne par lui-même consiste à changer le mode de cookie en "UseCookies" (les cookies sont nécessaires) dans le fichier web.config:

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

Selon mes tests, cela permet à SignOut de fonctionner de manière autonome, au détriment du coût de votre site, qui nécessite désormais le fonctionnement des cookies.

0
RogerMKE

Pour MVC, cela fonctionne pour moi:

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

Faire Session.abandon () et détruire le cookie fonctionne plutôt bien. J'utilise mvc3 et il semble que le problème se produise si vous accédez à une page protégée, déconnectez-vous et accédez à l'historique de votre navigateur. Pas un gros problème mais toujours un peu ennuyeux.

Essayer de passer par des liens sur mon application Web fonctionne bien.

Le paramétrer pour ne pas mettre en cache le navigateur peut être la solution.

0
James

Est-ce que vous testez/observez ce comportement en utilisant IE? Il est possible que IE serve ces pages depuis le cache. Il est notoirement difficile d’obtenir IE pour vider son cache, et à maintes reprises, même Une fois que vous vous êtes déconnecté, taper l'URL de l'une des pages "sécurisées" afficherait le contenu mis en cache d'avant.

(J'ai observé ce comportement même lorsque vous vous connectez en tant qu'utilisateur différent et IE affiche la barre "Bienvenue" en haut de votre page, avec le nom d'utilisateur de l'ancien utilisateur. De nos jours, généralement un reload le mettra à jour, mais s'il est persistant, il pourrait toujours s'agir d'un problème de mise en cache.)

0
Stobor