Thread.CurrentPrincipal 错误地声称是任意的

发布于 2024-09-16 10:52:41 字数 5473 浏览 4 评论 0原文

我在我的服务器上看到似乎是由任何匿名客户端发出的请求,尽管我确信它们是由经过身份验证的用户发出的 - 我有 fiddler 日志显示客户端发送了有效的 asp.net 身份验证 cookie 和服务器日志表明 cookie 已到达并且有效。所有浏览器中都观察到了该问题。

数据流是:

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

想法?

现在详细介绍:

极少数异步请求到达我的服务器(有证据表明它们没有被操纵或伪造)并且似乎是匿名的。在提出的 7 个请求中,某些请求可能有效也可能无效(即 5/7 将成功,2 个将失败)。成功/失败似乎没有任何模式。在我的请求似乎是匿名的情况下,CurrentPrincipal.Identity 记录:

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]

我知道身份验证 cookie 是有效的 - 在这些相同的请求期间,我能够解密身份验证 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.net 4.0,这个问题似乎变得更加严重,但我对这就是原因的信心不高。

我已经联系了一些遇到此问题的客户,这更令人沮丧(但确实反映了我能够在日志中读到的内容)。一旦陷入这种状态,就很难摆脱。清除缓存和cookie似乎没有效果。但是,切换到新的浏览器通常就可以了。同样,等待几个小时并使用相同的浏览器返回通常也可以,但并非总是如此。如前所述,所有浏览器都会出现这种情况。

有什么建议吗?
凯文




------------
以下是我捕获的日志片段的其余部分(已删除 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

I'm seeing requests on my server that appear to be made by an anynomous client, although I'm certain they were made by an authenticated user - I have fiddler logs showing that the client sent valid asp.net auth cookies, and server logs indicating that the cookie arrived and is valid. The problem has been observed across all browsers.

The flow of data is:

  1. User visits login url, on a machine that's part of a webfarm (all with the same machine, decrypt keys)
  2. On successful forms authentication, user is redirect to a restricted url, their homepage
  3. Homepage renders correctly, knowns the identify of the user, and includes javascript to perform 7 asynchronous post-backs to get additional data
  4. Javascript kicks off 7 http.get requests, hitting different machines in the webfarm (assume round robin)
  5. Server validates request: ~0.01% fail to authenticate.

Thoughts?

Now into details:

A very small number of the asynchronous requests land at my server (with evidence they were not manipulated or faked) and appear to be anonymous. Of the 7 requests made, some number may or may not work (ie, 5/7 will succeed, 2 will fail). There doesn't appear to be any patterns in success / failures. In the cases where my requests appear to be anonymous, the CurrentPrincipal.Identity records:

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

Dumping the http.context.request.params collection to a log file, I'm able to see the following relevent (and scrubbed) properties (complete params below):

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]

I know the auth cookie is valid - during these same requests I'm able to decrypt the auth cookie and extract the following:

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

Not sure how to proceed at this point. This problem seems to have been exacerbated with our recent migration to mvc 2.0 / asp.net 4.0, but my confidence isn't high that was the cause.

I've reached out to a handful of my customers who have had this problem, and that's been even more frustrating (but does reflect what I'm able to read in my logs). Once in this state, it's hard to get out of it. Clearing cache and cookies seem to have no effect. But, switching to a new browser and it's generally OK. Likewise, waiting several hours and returning with the same browser and it's also generally ok, but not always. As stated earlier, this is seen across all browsers.

Any suggestions?
Kevin

------------
Here is the remainder of the log snippet (scrubbed for pii) that I've captured:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

情未る 2024-09-23 10:52:41

这个答案有效,但同时令人失望和震惊。

我花了 2 个月的时间在 MSDN 技术支持部门兼职,我们终于找到了解决这个问题的方法。我将把这个问题留给 Microsoft 来解决,因为这几乎肯定是 .net 框架中的问题。但首先,让我总结一下问题,提供额外的相关背景信息以及我们在此过程中发现的一些有趣的事情。

症状转瞬即逝:我们的网站有一些用户报告,他们将通过我们的网站进行身份验证并看到正确的状态。但看似随机,他们会退出我们的网站,或者偶尔体验匿名视图。这是非常令人沮丧的,几乎不可能在本地、在室内复制。

另外,关于症状:通过日志记录,我们发现移动(iPhone、iPad 和 Android)浏览器受到了不成比例的影响,尽管所有浏览器和操作系统都受到了一定程度的影响。最后一个随机症状:某天它对用户有效,第二天就不行了,下午晚些时候,它又可以工作了。当然,切换浏览器几乎总能解决问题。

我们很快就假设存在身份验证问题,可能与身份验证 cookie 相关。奇怪的是,我能够证明(跟踪)出错的请求包含我能够解密的正确 cookie,但 .net 框架以非确定性方式忽略了这一点。我最终开始记录处于这种状态的所有请求 - .net 框架忽略了 auth cookie,但对我来说似乎有效,并发现大约 2% 的用户受到了影响。

我从使用 Thread.CurrentPrincipal.Identity 切换到 HttpContext.Current.User.Identity,但无济于事,并尝试了一些其他设置。奇怪的是,我能够做出的唯一能产生影响的改变是迁移到 .net 4 框架(从 3.5 开始)。这个问题变得更严重了。还尝试了各种负载均衡器配置,并且能够排除多个机器配置——发出 auth cookie 的同一台机器稍后会拒绝它。

重申一下症状:我们有某些用户(非确定性),他们有时无法以身份验证模式(也是非确定性)使用我们的网站。可爱的。

现在,雷德蒙德的产品团队已经介入,也陷入了困境。但他们确实提出了一个建议,最终解决了这个问题,如下:
尝试强制 Microsoft.net 框架使用 cookie 作为身份验证模式,而不是使用无 cookie 状态:

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

打开开关,有问题的请求立即结束(一旦我使处于奇怪状态的会话过期)。

虽然我很高兴问题得到了解决——或者更确切地说是解决了,但令我担心的是各种浏览器的非确定性处理。为什么 .net 框架有一天会看到浏览器,并将其视为支持 cookie,然后在同一天晚些时候说它应该使用无 cookie 会话?

我最后关心的是有多少其他网站在不知情的情况下丢失了 2% 的经过身份验证的流量?考虑到该修复,感觉很像 .net 4 框架中的一个错误。

This answer works, but is disappointing and alarming at the same time.

I spent 2 months working part time with MSDN technical support, and we finally found a work-around for this problem. I'm going to leave it to Microsoft to fix the problem, as it’s almost certainly an issue in the .net framework. But first, let me summarize the problem, give additional relevant background information and a few interesting things we found along the way.

The symptom was fleeting: Our website had a few reports of users who would authenticate with our website and see the correct state. But seemingly randomly, they’d be signed out of our website, or occasionally, experience the anonymous view. It was very frustrating, an nearly impossible to reproduce locally, in house.

Also on symptoms: through logging we saw mobile (iphone, ipad & android) browsers were disproportionately impacted, although all browsers and operating systems were impacted to some degree. And one last random symptom: It’d work for a user one day, not the next, and later in the afternoon, work again. Of course, switching browsers almost always fixed the problem.

We quickly assumed an auth issue, likely around the authentication cookie. The strange part was, I was able to prove (tracing) that the requests that were erroring included a proper cookie that I was able to decrypt, but that the .net framework was ignoring, in a non-deterministic way. I eventually began logging all requests that were in this state – auth cookie ignored by the .net framework, but seemingly valid to me, and found around 2% of my users were impacted.

I switched from using Thread.CurrentPrincipal.Identity to HttpContext.Current.User.Identity, to no avail, and tried a handful of other settings. Curiously, the only change I was able to make that made a dent was migrate to the .net 4 framework (from 3.5). The problem became an order of magnitude worst. Also tried various load balancer configurations, and was able to rule out multiple machine configurations – the same machine that issued the auth cookie would later reject it.

To re-iterate the symptoms: we had certain users (non-deterministic) who at times would not be able to user our website in an authenticated mode (also non-deterministic). Cute.

By now, the product team in Redmond was involved, and also stumped. But they did come up with a suggestion, which ultimately resolved the issue, here goes:
Try forcing the Microsoft.net framework to use cookies as the authentication mode, as opposed to using a cookieless state:

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

Flipped the switch and instantly the problematic requests ended (once I expired the session of those in an odd state).

While I’m glad that the problem was resolved – or rather worked around, it’s the non-deterministic handling of various browsers that worries me. Why would the .net framework see a browser one day, and treat it as supporting cookies, and later the same day say it should use a cookieless session?

My last concern is around how many other sites out there are losing 2% of their authenticated traffic without knowing? Considering the fix, it feels very much like a bug in the .net 4 framework.

提笔落墨 2024-09-23 10:52:41

不要在 ASP.NET 身份验证中使用此方法:

Thread.CurrentPrincipal =principal;

而是坚持:

HttpContext.Current.User = principal;

有关信息,请参阅这篇文章链接文本,但更重要的是评论,包括第一个和最后一个 - 文章是 2004 年的旧文章,但论点今天仍然有效。

因此,应改为:

Thread.CurrentPrincipal.Identity.IsAuthenticated; // 错误的
Thread.CurrentPrincipal.Identity.Name; // null(或空,不确定)

您应该使用:

 HttpContext.Current.User.Identity...

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

Don't use this in ASP.NET authentication:

Thread.CurrentPrincipal = principal;

Instead stick to:

HttpContext.Current.User = principal;

For info see this article link text but more importantly the comments including the first and last ones - the article is old 2004 but the arguments are still valid today.

Therefore, instead of:

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

You should use:

 HttpContext.Current.User.Identity...

In which case you can also use AuthenticateRequest instead of PostAuthenticateRequest because there is no Thread issue to workaround.

狼性发作 2024-09-23 10:52:41

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

我建议您创建自己的模块,在其他模块之前调用该模块,然后您自己检查 cookie 是否存在,然后如果存在则对其进行解码以查看其包含的内容。这将为您提供有关所发生情况的更多详细信息。您自己的模块可重用 FormsAuthentication 模块中的方法来执行这些操作。例如....

ForsmAuthentication.Decrypt(...)

I would recommend that you begin by checking that the incoming web request actually has an authentication cookie and that it is valid. The forms authentication module takes the incoming web request and looks to see if it has a authentication cookie. If so then it attempts to decode it and then generate the principle using its contained value. As your principle is empty it means that either there was no authentication cookie provided in the request or there was an error decoding or it was decoded and found to be expired or it was decoded and oddly it has empty string as the username.

I recommend you create your own module that is called before the others and you check for yourself if the cookie is present and then if present decode it to see what it contains. That would give you more detail on what it happening. Your own module to reuse methods from the FormsAuthentication module to perform these actions. Such as....

ForsmAuthentication.Decrypt(...)
酒浓于脸红 2024-09-23 10:52:41

这是我在大多数需要基本身份验证的 ASP.NET / Mvc 应用程序中使用的身份验证。我相信这会有所帮助,并允许您在 AuthenticationCookie 中存储附加数据。如果您在 .Net 进行身份验证之前使用此选项,.Net 将覆盖您当前主体和用户属性的设置,使用 PostAuthenticateRequest 将解决覆盖问题。如果您有任何疑问,请告诉我。


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

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

Here is the authentication I use with most of my ASP.NET / Mvc applications that needs basic authentication. I believe it would help and would allow you to store additional data in the AuthenticationCookie. If you use this before .Net does their authentication .Net will override your setting of the current principal and user properties, using the PostAuthenticateRequest will fix the overriding issue. Let me know if you have any 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
}

I Hope this helps to solve your issue.

月野兔 2024-09-23 10:52:41

重新赏金:

我在使用 asp.net 4.0 的 Azure 应用程序中看到了这一点,cookie 就在那里,您可以使用 FormsAuthentication.Decrypt 对其进行解密并读取所有内容(未过期、正确的值等);就像OP所描述的那样。与OP场景不同,我已经在使用UseCookies,并且仍然得到相同的结果。赏金是针对 ASP.NET 中可能触发此问题和解决方案的特定原因。

我的案例是一个非常愚蠢的问题:

  1. 通过 FormsAuthentication.SetAuthCookie 发出令牌和相应的重定向
  2. 在 web.config 中配置 标记
  3. 检查 User。页面 / 中的 Identity.IsAuthenticated 为 false
  4. cookie 在那里,您甚至可以通过 FormsAuthentication.Decrypt 解密

它 问题:不要忘记设置 ,哈哈,完全失败......

我对OP的2美分:当尝试使用无cookie授权时,一些内部链接/重定向/js可能会造成严重破坏。此外,cookie 支持检测不是很精确。

re bounty:

I'm seeing this in an Azure application with asp.net 4.0, cookie is there and you can decrypt it with FormsAuthentication.Decrypt and read everything (not expired, correct value, etc, etc); just like the OP described. Unlike the OP scenario, I was already using UseCookies, and still get the same. Bounty is for the specific reason within asp.net that can trigger this problem and solution.

My case was such a silly issue:

  1. Issue tokens via FormsAuthentication.SetAuthCookie and a corresponding redirect
  2. Configure the <forms> tag in the web.config
  3. Check User.Identity.IsAuthenticated in the page / is false
  4. The cookie is there and you can even decrypt it via FormsAuthentication.Decrypt

problem: don't forget to set <authentication mode="Forms">, lol, total fail ...

My 2 cents on the OP: some internal links/redirects/js can break havoc when trying to use cookieless authorization. Additionally cookie support detection is not very precise.

疯了 2024-09-23 10:52:41

根据我过去的经验,我认为这个问题实际上是由于ASP.NET无法识别IE10+引起的。由于不知道浏览器及其功能,它会退回到无 cookie 身份验证(一个糟糕的或至少过时的假设)。

浏览器定义文件的更新已在此处发布。 .NET 4.5 不存在此问题

https://support.microsoft.com/kb/2600088

http://support.microsoft.com/kb/2600100

http://support.microsoft.com/kb/2608565

I believe, based on my past experience, that this issue is in fact caused by ASP.NET not recognizing IE10+. Not known the browser and its capabilities, it falls back to cookieless authentication (a bad or at least outdated assumption).

Updates for the browser definition files were released available here. The problem is not present with .NET 4.5

https://support.microsoft.com/kb/2600088

http://support.microsoft.com/kb/2600100

http://support.microsoft.com/kb/2608565

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文