代码之家  ›  专栏  ›  技术社区  ›  Kevin

线程.CurrentPrincipal错误地声称是任何合法的

  •  30
  • Kevin  · 技术社区  · 16 年前

    数据流是:

    1. 用户访问登录url,在属于webfarm的一部分的计算机上(都使用相同的计算机,解密密钥)
    2. 一旦表单验证成功,用户将被重定向到一个受限制的url,即他们的主页
    3. 主页呈现正确,知道用户的身份,并包含javascript执行7个异步回发以获取额外数据
    4. Javascript启动7http.get获取请求,命中webfarm中的不同计算机(假设循环)
    5. 服务器验证请求:~0.01%验证失败。

    思想?

    现在进入细节:

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

    倾倒http.context.request请求.params集合到日志文件,我可以看到以下相关(和已清除)属性(下面的完整参数):

    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]
    

    我知道auth cookie是有效的-在这些请求期间,我能够解密auth cookie并提取以下内容:

    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
    

    现在不知道该怎么办。随着我们最近向mvc 2.0/asp.net4.0,但我的信心不高那是原因。

    有什么建议吗?
    凯文




    ------------
    以下是我捕获的日志片段的剩余部分(为pii而清理):

    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
    
    6 回复  |  直到 16 年前
        1
  •  20
  •   Kevin    16 年前

    这个答案是可行的,但同时也令人失望和担忧。

    症状是转瞬即逝的:我们的网站有一些报告的用户谁将验证我们的网站,并看到正确的状态。但似乎是随机的,他们可能会被注销我们的网站,或偶尔,体验匿名查看。这是非常令人沮丧的,一个几乎不可能在本地繁殖,在家里。

    症状方面:通过日志记录,我们看到移动(iphone、ipad和android)浏览器受到了不成比例的影响,尽管所有浏览器和操作系统都受到了一定程度的影响。最后一个随机症状是:Itd在某一天对某个用户有效,而不是第二天,下午晚些时候,它会再次工作。当然,切换浏览器几乎总能解决问题。

    重新迭代症状:我们有一些用户(不确定),他们有时无法以身份验证模式(也不确定)使用我们的网站。可爱的。

    试着强迫微软.net框架使用Cookie作为身份验证模式,而不是使用无Cookie状态:

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

    打开开关,有问题的请求立即结束(一旦我终止了处于奇数状态的请求的会话)。

    虽然我很高兴问题得到了解决,或者说得到了解决,但我担心的是各种浏览器的不确定性处理。为什么.net framework某天会看到一个浏览器,并将其视为支持cookies,而同一天稍后会说它应该使用无cookie会话?

        2
  •  2
  •   Barry Kaye    16 年前

    别用这个ASP.NET身份验证:

    Thread.CurrentPrincipal = principal;

    HttpContext.Current.User = principal;
    

    有关信息,请参阅本文 link text 但更重要的是,包括第一条和最后一条在内的评论——这篇文章是2004年的老文章,但论据至今仍然有效。

    因此,不是:

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

    您应该使用:

     HttpContext.Current.User.Identity...
    

    在这种情况下,还可以使用AuthenticateRequest而不是PostAuthenticateRequest,因为没有线程问题需要解决。

        3
  •  0
  •   Phil Wright    16 年前

    我建议您首先检查传入的web请求是否确实有身份验证cookie,并且它是否有效。表单身份验证模块接收传入的web请求并查看它是否具有身份验证cookie。如果是这样的话,那么它会尝试对其进行解码,然后使用其包含的值生成原理。由于您的原则是空的,这意味着请求中没有提供身份验证cookie,或者解码时出错,或者被解码并发现过期,或者被解码,奇怪的是,它的用户名为空字符串。

    我建议您先创建自己的模块,然后再调用其他模块,然后自己检查cookie是否存在,如果存在,则对其进行解码以查看它包含什么。这会给你更多的细节。您自己的模块可以重用FormsAuthentication模块中的方法来执行这些操作。比如。。。。

    ForsmAuthentication.Decrypt(...)
    
        4
  •  0
  •   sbaker    16 年前

    
    // 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
    }
    

    我希望这有助于解决你的问题。

        5
  •  0
  •   eglasius    13 年前

    我在一个有asp.net4.0,cookie就在那里,你可以用FormsAuthentication.解密并读取所有内容(未过期、正确值等);就像OP描述的那样。与OP场景不同的是,我已经在使用UseCookies了,而且仍然得到相同的结果。赏金是出于某种特定的原因asp.net会引发这个问题和解决方案。

    我的案子真是个愚蠢的问题:

    1. 通过发行代币 FormsAuthentication.SetAuthCookie 以及相应的重定向
    2. <forms> 标签在web.config文件
    3. User.Identity.IsAuthenticated 在页面中/为false
    4. cookie就在那里,你甚至可以通过 FormsAuthentication.Decrypt

    问题:别忘了设置 <authentication mode="Forms">

    我的2美分的OP:一些内部链接/重定向/js可以打破破坏时 尝试 使用无Cookie授权。另外,cookie支持检测不是很精确。

        6
  •  0
  •   Richard Collette    12 年前