30 votes

Thread.CurrentPrincipal prétend à tort être anonyme

Je vais voir des demandes sur mon serveur qui semblent être faites par un anynomous client, même si je suis certains qu'ils ont été faites par un utilisateur authentifié - j'ai fiddler journaux montrant que le client a envoyé valide asp.net auth les cookies, et les journaux de serveur indiquant que le cookie est arrivé et est valide. Le problème a été observé sur tous les navigateurs.

Le flux des données est:

  1. Visites de l'utilisateur l'url de connexion, sur une machine faisant partie d'un webfarm (tous avec la même machine, décrypter les clés)
  2. La réussite de l'authentification de formulaires, l'utilisateur est rediriger vers une restriction de l'url de leur page d'accueil
  3. Page d'accueil s'affiche correctement, appelés l'identité de l'utilisateur, et comprend javascript pour effectuer des 7 asynchrone post-dos pour obtenir des données supplémentaires
  4. Javascript coup d'envoi de la 7 http.les requêtes get, frapper les différentes machines dans le webfarm (à supposer round robin)
  5. Serveur valide la demande: ~0.01% ne parviennent pas à s'authentifier.

Pensées?

Maintenant dans les détails:

Un très petit nombre de requêtes asynchrones terre à mon serveur (avec la preuve qu'ils n'étaient pas manipulés ou faux) et semblent être anonyme. Du 7 demandes, un certain nombre peut ou peut ne pas fonctionner (c'est à dire, 5/7 va réussir, 2 échouera). Il ne semble pas être n'importe quel des modèles de réussite ou d'échec. Dans le cas où ma demande semble être anonyme, le CurrentPrincipal.L'identité des enregistrements:

Thread.CurrentPrincipal.Identity.IsAuthenticated; // false
Thread.CurrentPrincipal.Identity.Name; // null (or empty, unsure off hand)

Dumping http.contexte.demande.params collection dans un fichier journal, je suis en mesure de voir la suite pertinents (et nettoyée) propriétés (complet params ci-dessous):

context: {"userId":10000,"userName":"johnsmith"}
HTTP_COOKIE:.ASPXAUTH=[valid auth cookie value]
HTTP_X_REQUESTED_WITH:XMLHttpRequest
X-Requested-With: XMLHttpRequest
    AUTH_TYPE: 
    AUTH_USER: 
    AUTH_PASSWORD: 
    LOGON_USER: 
    REMOTE_USER: 
    HTTP_COOKIE: .ASPXAUTH=[valid auth cookie value]

Je sais que l'auth cookie est valide - au cours de ces mêmes requêtes que je suis en mesure de déchiffrer les auth cookie et extraire les éléments suivants:

CookiePath: /
Expiration: 9/23/2105 8:14:22 PM
Expired: False
IsPersistent: True
IssueDate: 8/30/2010 2:54:22 PM
Name: johnsmith
UserData: 
Version: 2

Pas sûr de savoir comment procéder à ce point. Ce problème semble avoir été exacerbée avec notre récente migration mvc 2.0 / asp.net 4.0, mais ma confiance n'est pas élevé qui en était la cause.

J'en suis arrivé à une poignée de mes clients qui ont eu ce problème, et c'est encore plus frustrant (mais ne reflètent ce que je suis capable de lire dans les journaux). Une fois dans cet état, il est difficile de s'en sortir. Effacer la mémoire cache et les cookies semblent avoir aucun effet. Mais, le passage à une nouvelle fenêtre de navigateur, et il est généralement OK. De même, une attente de plusieurs heures et revenir avec le même navigateur et il est aussi généralement ok, mais pas toujours. Comme indiqué précédemment, cela se voit sur tous les navigateurs.

Toutes les suggestions?
Kevin




------------
Voici le reste de l'extrait de journal (nettoyée pour pii) que j'ai capturé:

8/30/2010 2:54:43 PM: Anonymous user detected:
    Identity Name:
    IsAuthenticated::False
HttpContextInformation to follow:

8/30/2010 2:54:43 PM: Request Param collection contents:
context: {"userId":10000,"userName":"johnsmith"}
    .ASPXAUTH: A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
    ASP.NET_SessionId: m5vit3cyv0rsiosqg5xmhhuu
    ALL_HTTP: HTTP_CONNECTION:close
HTTP_ACCEPT:text/javascript, text/html, application/xml, text/xml, */*
HTTP_ACCEPT_ENCODING:gzip, deflate
HTTP_ACCEPT_LANGUAGE:en-us
HTTP_COOKIE:.ASPXAUTH=A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
HTTP_HOST:www.host.com
HTTP_REFERER:http://www.host.com/
HTTP_USER_AGENT:Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
HTTP_X_FORWARDED_FOR:166.137.139.139
HTTP_X_REQUESTED_WITH:XMLHttpRequest

    ALL_RAW: Connection: close
Accept: text/javascript, text/html, application/xml, text/xml, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Cookie: .ASPXAUTH=A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
Host: www.host.com
Referer: http://www.host.com/
User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
X-Forwarded-For: 166.137.139.139
X-Requested-With: XMLHttpRequest

    APPL_MD_PATH: /LM/W3SVC/792523/Root
    APPL_PHYSICAL_PATH: d:\localpath\
    AUTH_TYPE: 
    AUTH_USER: 
    AUTH_PASSWORD: 
    LOGON_USER: 
    REMOTE_USER: 
    CERT_COOKIE: 
    CERT_FLAGS: 
    CERT_ISSUER: 
    CERT_KEYSIZE: 
    CERT_SECRETKEYSIZE: 
    CERT_SERIALNUMBER: 
    CERT_SERVER_ISSUER: 
    CERT_SERVER_SUBJECT: 
    CERT_SUBJECT: 
    CONTENT_LENGTH: 0
    CONTENT_TYPE: 
    GATEWAY_INTERFACE: CGI/1.1
    HTTPS: off
    HTTPS_KEYSIZE: 
    HTTPS_SECRETKEYSIZE: 
    HTTPS_SERVER_ISSUER: 
    HTTPS_SERVER_SUBJECT: 
    INSTANCE_ID: 792523
    INSTANCE_META_PATH: /LM/W3SVC/792523
    LOCAL_ADDR: 10.248.50.207
    PATH_INFO: /resource
    PATH_TRANSLATED: d:\localpath\resource
    QUERY_STRING: context={%22userId%22:10000,%22userName%22:%22johnsmith%22}
    REMOTE_ADDR: 10.208.205.171
    REMOTE_HOST: 10.208.205.171
    REMOTE_PORT: 37966
    REQUEST_METHOD: GET
    SCRIPT_NAME: /resouce
    SERVER_NAME: www.host.com
    SERVER_PORT: 80
    SERVER_PORT_SECURE: 0
    SERVER_PROTOCOL: HTTP/1.0
    SERVER_SOFTWARE: Microsoft-IIS/6.0
    URL: /resource
    HTTP_CONNECTION: close
    HTTP_ACCEPT: text/javascript, text/html, application/xml, text/xml, */*
    HTTP_ACCEPT_ENCODING: gzip, deflate
    HTTP_ACCEPT_LANGUAGE: en-us
    HTTP_COOKIE: .ASPXAUTH=A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
    HTTP_HOST: www.host.com
    HTTP_REFERER: http://www.host.com/
    HTTP_USER_AGENT: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
    HTTP_X_FORWARDED_FOR: 166.137.139.139
    HTTP_X_REQUESTED_WITH: XMLHttpRequest


8/30/2010 2:54:43 PM: Auth Ticket collection contents:
    CookiePath: /
    Expiration: 9/23/2105 8:14:22 PM
    Expired: False
    IsPersistent: True
    IssueDate: 8/30/2010 2:54:22 PM
    Name: johnsmith
    UserData: 
    Version: 2

20voto

Kevin Points 543

Cette réponse fonctionne, mais c'est décevant et inquiétant en même temps.

J'ai passé 2 mois de travail à temps partiel avec MSDN support technique, et nous avons finalement trouvé une solution de contournement pour ce problème. Je vais laisser de Microsoft pour résoudre le problème, car il est presque certainement un problème dans le .net framework. Mais d'abord, permettez-moi de résumer le problème, donner plus d'information pertinent de l'information et de quelques petites choses intéressantes, nous avons trouvé le long du chemin.

Le symptôme fut éphémère: Notre site a eu quelques rapports d'utilisateurs qui s'authentifient avec notre site web et voir l'état correct. Mais apparemment au hasard, ils avaient signé de notre site web, ou parfois, l'expérience de l'anonyme de vue. C'était très frustrant, un presque impossible à reproduire localement, dans la maison.

Également sur les symptômes: par l'exploitation du bois, nous avons vu mobile (iphone, ipad & android), les navigateurs ont été touchés de façon disproportionnée, bien que tous les navigateurs et systèmes d'exploitation ont été touchées à divers degrés. Et une dernière aléatoire symptôme: Il avait un travail pour un utilisateur un jour, pas le lendemain, et plus tard dans l'après-midi, le travail à nouveau. Bien sûr, la commutation des navigateurs presque toujours résolu le problème.

Nous avons rapidement pris une auth question, probablement autour du cookie d'authentification. La partie étrange a été, j'ai été en mesure de prouver (traçage) que les demandes qui ont été erroring inclus un cookie que j'ai pu déchiffrer, mais que l' .net framework a été ignorant, dans un non-déterministe façon. J'ai finalement commencé à enregistrer toutes les demandes qui ont été dans cet état – auth cookie ignoré par la .net framework, mais apparemment valable pour moi, et a trouvé environ 2% de mes utilisateurs ont été touchés.

Je suis passé de l'aide de Fil.CurrentPrincipal.L'identité de HttpContext.Actuel.De l'utilisateur.L'identité, en vain, et j'ai essayé une poignée d'autres paramètres. Curieusement, le seul changement que j'ai pu faire qui fait une brèche a été de migrer vers la .net 4 cadre (à partir de 3,5). Le problème devient un ordre de grandeur pire. Aussi essayé différents équilibrage de la charge de configurations, et a été en mesure d'écarter plusieurs configurations de machine – la même machine que celle qui a délivré le auth cookie plus tard le rejeter.

À réitérer les symptômes: nous avons eu certains utilisateurs (non-déterministe) qui à la fois ne serait pas en mesure d'utilisateur de notre site web dans un mode authentifié (non-déterministe). Mignon.

Maintenant, l'équipe produit de Redmond a été impliqué, et aussi perplexe. Mais ils ne viennent avec une suggestion, qui a finalement résolu le problème, va ici: Essayer de forcer l'Microsoft.net cadre pour l'utilisation de cookies que le mode d'authentification, par opposition à l'aide d'un cookieless état:

<authentication mode="Forms">
  <forms cookieless="UseCookies" />
</authentication>

Renversé le commutateur et instantanément la problématique des demandes terminé (une fois que je l'expiration de la session de ceux qui, dans un étrange état).

Même si je suis content que le problème a été résolu – ou plutôt de contourner, c'est la non-déterministe de la manipulation de divers navigateurs qui m'inquiète. Pourquoi l' .net framework est un navigateur, un jour, et la traiter comme soutien des cookies, et, plus tard, le jour même de dire qu'il devrait utiliser une session cookieless?

Ma dernière préoccupation est d'environ combien d'autres sites là-bas sont en train de perdre 2% de leur authentifié de la circulation sans le savoir? Compte tenu de la correction, il se sent beaucoup comme un bug dans le .net 4 cadre.

1voto

Barry Kaye Points 5722

Ne pas l'utiliser dans ASP.NET authentification:

Thread.CurrentPrincipal = principal;

Au lieu de rester à:

HttpContext.Current.User = principal;

Pour plus d'informations, voir cet article texte du lien , mais plus important encore, les commentaires, y compris la première et de la dernière - l'article est vieux en 2004, mais les arguments sont encore valables aujourd'hui.

Donc, au lieu de:

Thread.CurrentPrincipal.Identity.IsAuthenticated; // false Thread.CurrentPrincipal.Identity.Name; // null (or empty, unsure off hand)

Vous devez utiliser:

 HttpContext.Current.User.Identity...

Dans ce cas, vous pouvez également utiliser AuthenticateRequest au lieu de PostAuthenticateRequest parce qu'il n'y a pas de Fil problème à la solution de contournement.

0voto

Phil Wright Points 11696

Je vous recommande de commencer par vérifier que les requêtes web entrantes a effectivement un cookie d'authentification et qu'il est valide. Les formulaires d'authentification module utilise les requêtes web entrantes et regarde pour voir si il a un cookie d'authentification. Si oui, alors il tente de décoder puis de générer le principe à l'aide de ses contenus valeur. Votre principe est vide, cela signifie que soit il n'y a pas de cookie d'authentification fournis dans la demande ou s'il y avait une erreur de décodage ou il a été décodé et trouvé pour être expiré ou a été décodé et bizarrement, il a une chaîne vide comme le nom d'utilisateur.

Je vous recommande de créer votre propre module qui est appelée avant les autres, et que vous le vérifier vous-même si le cookie est présent et puis si présent décoder de manière à voir ce qu'il contient. Qui vous donnent plus de détails sur ce qu'il se passe. Votre propre module de réutiliser les méthodes de la FormsAuthentication module pour effectuer ces actions. Comme....

ForsmAuthentication.Decrypt(...)

0voto

Stephen Baker Points 21

Voici l'authentification-je utiliser avec la plupart de mes ASP.NET / applications Mvc qui a besoin de l'authentification de base. Je crois qu'il serait utile et vous permettra de stocker des données supplémentaires dans le AuthenticationCookie. Si vous utilisez cette avant .Net ne leur authentification .Net remplacera votre réglage du courant principal et les propriétés de l'utilisateur, à l'aide de la PostAuthenticateRequest va résoudre la question primordiale. Laissez-moi savoir si vous avez des questions.


// Code that goes in the Global.asax.cs
// that runs after .Net has done it's authentication
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    IPrincipal user = HttpContext.Current.User;

    if (user == null) { return; }

    FormsIdentity formsIdentity = user.Identity as FormsIdentity;

    if (formsIdentity == null || !formsIdentity.IsAuthenticated) { return; }

    Principal principal = new Principal(new Identity(formsIdentity.Ticket));
    HttpContext.Current.User = principal;
    Thread.CurrentPrincipal = principal;
}

// Base implementation of the System.Security.Principal.IPrincipal interface.
public class Principal : System.Security.Principal.IPrincipal
{
    #region Fields

    private IIdentity _identity = null;

    #endregion

    #region Constructors

    public Principal(IIdentity identity)
    {
        _identity = identity;
    }

    #endregion

    #region Properties

    public IIdentity Identity
    {
        get
        {
            return _identity;
        }
    }

    #endregion

    #region Methods

    public bool IsInRole(string role)
    {
        return (_identity != null && _identity.IsAuthenticated);
    }

    #endregion
}



// Base implementation of the System.Security.Principal.IIdentity interface. 
public class Identity : System.Security.Principal.IIdentity
{
    #region Fields

    private readonly int _userId;
    private readonly bool _isAuthenticated;
    private readonly string _userName;

    #endregion

    #region Constructors

    public Identity(FormsAuthenticationTicket formsAuthTicket)
    {
        if (formsAuthTicket == null)
        {
            throw new NullReferenceException("FormsAuthenticationTicket may not be null.");
        }

        if (string.IsNullOrEmpty(formsAuthTicket.UserData))
        {
            throw new NullReferenceException("FormsAuthenticationTicket.UserData may not be null or empty.");
        }

        string[] userData = formsAuthTicket.UserData.Split(new[] {"|"}, StringSplitOptions.RemoveEmptyEntries);

        if (userData.Length < 1)
        {
            throw new ArgumentOutOfRangeException("formsAuthTicket", userData, "UserData does not contain a UserId and or a SiteId");
        }

        _userId = Convert.ToInt32(userData[0]);
        _isAuthenticated = !formsAuthTicket.Expired;
        _userName = formsAuthTicket.Name;
    }

    #endregion

    #region Properties

    public int UserId
    {
        get
        {
            return _userId;
        }
    }
    public string AuthenticationType
    {
        get
        {
            return "Forms";
        }
    }
    public bool IsAuthenticated
    {
        get
        {
            return _isAuthenticated;
        }
    }
    public string Name
    {
        get
        {
            return _userName;
        }
    }

    #endregion
}

J'Espère que cela vous aide à résoudre votre problème.

0voto

eglasius Points 26221

re bounty:

Je le vois dans une application avec Azure asp.net 4.0, cookie est là et vous pouvez décrypter avec FormsAuthentication.Déchiffrer et à lire tout (pas expiré, valeur correcte, etc, etc); tout comme l'OP décrit. À la différence de l'OP scénario, j'étais déjà à l'aide de Utilisercookies, et encore obtenir le même. Bounty est pour la raison spécifique au sein de asp.net qui peut déclencher ce problème et la solution.

Mon cas était une bête question:

  1. Émettre des jetons via FormsAuthentication.SetAuthCookie et un correspondant de redirection
  2. Configurer l' <forms> balise dans le web.config
  3. Vérifiez User.Identity.IsAuthenticated dans la page / est faux
  4. Le cookie est là et vous pouvez même le décrypter via FormsAuthentication.Decrypt

problème: n'oubliez pas d' <authentication mode="Forms">, lol, total fail ...

Mes 2 cents sur l'OP: certains liens internes/redirections/js peut briser des ravages lorsque essayant d'utiliser cookieless autorisation. En outre le support des cookies, la détection n'est pas très précis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X