Question

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.

Était-ce utile?

La solution

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 se trouve dans l'espace de noms System.Web . Référence MSDN .

Autres conseils

Cela me semble que votre section d’autorisation web.config n’est pas correctement configurée. 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>

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 de la déconnexion:

  • Vous devez d’abord effacer les cookies d’authentification et 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 sur la manière 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" ); 
    }
    

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 du navigateur, ou en le tapant, 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 également appeler:

Response.Cache.SetNoStore();

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 si il 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 en cours 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 également vérifier vos variables de session!

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

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>

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é qu'il était impossible d'accéder aux pages avant la connexion?

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

J'ai écrit une classe 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 effectuant le suivi, 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 avait deux solutions. Soit 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 deuxième 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 pourra aider quelqu'un

Cordialement

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 du navigateur me prenne en charge 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 vous aidera

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

Trouvez-le ici: http://forums.asp.net/t/1306526. aspx / 1

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

En général, pour effacer une session d'utilisateur, procédez ainsi

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

déconnectera effectivement 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), vous constaterez que

Request.isAuthenticated == true

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

La seule chose qui a fonctionné a été faire

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

Cela définit effectivement Request.isAuthenticated = false .

Cela m'est arrivé lorsque j'ai défini l'authentification > formes > Propriété de chemin dans Web.config . Supprimer ce problème a permis de résoudre le problème. Un simple FormsAuthentication.SignOut (); a à nouveau supprimé le cookie.

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

Je viens d'avoir le même problème, où SignOut () n'a apparemment 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 a sans doute été que la page a été redirigée au mauvais moment, ce qui n'a pas déclenché l'authentification.

J'ai un problème similaire maintenant et je pense 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);

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

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

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

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

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

Testez-vous / observez-vous ce comportement en utilisant IE? Il est possible qu'IE serve ces pages à partir du cache. Il est notoirement difficile à IE de vider son cache, et ainsi souvent, même après vous être déconnecté, en tapant l’URL de l’un des fichiers "sécurisé". les pages afficheraient le contenu mis en cache d’avant.

(J'ai observé ce problème 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, un rechargement le met à jour. , mais si elle est persistante, il pourrait toujours s'agir d'un problème de mise en cache.)

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 très grave, mais toujours un peu ennuyeux.

Essayer de passer par les liens de mon application Web fonctionne correctement.

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

Pour MVC, cela fonctionne pour moi:

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

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 par formulaire   à partir du cookie ou de l'URL si CookiesSupported est false .

Dans le même temps, disent-ils :

  

Une des valeurs HttpCookieMode qui indique si le   L’application est configurée pour l’authentification des formulaires 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, le   La propriété CookiesSupported retournera la valeur true si le navigateur pour le   La requête en cours prend en charge les cookies et la redirection par 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 avoir pour effet que CookiesSupported soit 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 requis) dans le fichier web.config:

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

Selon mes tests, cette opération permet à SignOut de fonctionner de manière autonome, au détriment du coût de votre site nécessitant désormais le bon fonctionnement des cookies.

Sachez que WIF refuse de demander au navigateur de nettoyer les cookies si le message wsignoutcleanup de STS ne correspond pas à l'URL avec le nom de l'application d'IIS, et je veux dire CAS SENSITIVE . WIF répond par le chèque vert OK, mais pas envoie la commande de suppression des cookies au navigateur.

Donc, vous devez faire attention à la sensibilité à la casse de votre URL.

Par exemple, ThinkTecture Identity Server enregistre les URL des RPs visiteurs dans un cookie, mais les rend tous en minuscules. WIF recevra le message wsignoutcleanup en minuscule et le comparera au nom de l'application dans IIS. Si cela ne correspond pas, aucun cookie ne sera supprimé, mais OK sera signalé au navigateur. Donc, pour cet Identity Server, je devais écrire toutes les URL dans web.config et tous les noms d’application dans IIS en minuscules, afin d’éviter de tels problèmes.

N'oubliez pas non plus d'autoriser les cookies tiers dans le navigateur si vos applications se trouvent en dehors du sous-domaine de STS, sinon le navigateur ne les supprimera pas même si WIF le lui dit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top