C# Thread.CurrentPrincipal错误地声明为anynomous
我在我的服务器上看到的请求似乎是由任意客户端发出的,尽管我确定它们是由经过身份验证的用户发出的-我有fiddler日志显示客户端发送了有效的asp.net身份验证cookie,服务器日志显示cookie已到达且有效。在所有浏览器中都观察到了该问题 数据流是:C# Thread.CurrentPrincipal错误地声明为anynomous,c#,asp.net,asp.net-mvc,authentication,forms-authentication,C#,Asp.net,Asp.net Mvc,Authentication,Forms Authentication,我在我的服务器上看到的请求似乎是由任意客户端发出的,尽管我确定它们是由经过身份验证的用户发出的-我有fiddler日志显示客户端发送了有效的asp.net身份验证cookie,服务器日志显示cookie已到达且有效。在所有浏览器中都观察到了该问题 数据流是: 用户在属于webfarm的计算机上访问登录url(都使用同一台计算机,解密密钥) 一旦表单验证成功,用户将被重定向到一个受限制的url,即他们的主页 主页正确呈现,知道用户的身份,并包含javascript以执行7次异步回发以获取附加数据
Thread.CurrentPrincipal.Identity.IsAuthenticated; // false
Thread.CurrentPrincipal.Identity.Name; // null (or empty, unsure off hand)
将http.context.request.params集合转储到日志文件中,我可以看到以下相关(和已清除)属性(下面是完整的参数):
我知道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
现在不知道该如何进行。随着我们最近向MVC2.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
我建议您首先检查传入的web请求是否确实具有身份验证cookie,并且该cookie是否有效。表单身份验证模块接受传入的web请求,并查看它是否具有身份验证cookie。如果是这样的话,它会尝试对其进行解码,然后使用其包含的值生成原理。由于您的原则是空的,这意味着请求中没有提供身份验证cookie,或者解码错误,或者被解码并发现已过期,或者被解码,奇怪的是,用户名为空字符串 我建议您创建自己的模块,该模块在其他模块之前调用,您自己检查cookie是否存在,然后如果存在,则对其进行解码以查看其包含的内容。这会给你更多关于它发生的细节。您自己的模块可以重用FormsAuthentication模块中的方法来执行这些操作。比如
ForsmAuthentication.Decrypt(...)
以下是我对大多数需要基本身份验证的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;
}
//System.Security.Principal.IPrincipal接口的基本实现。
公共类负责人:System.Security.Principal.IPrincipal
{
#区域字段
私有身份_identity=null;
#端区
#区域构造函数
公共负责人(身份识别)
{
_身份=身份;
}
#端区
#区域属性
公共身份识别
{
得到
{
返回标识;
}
}
#端区
#区域方法
公共布尔IsInRole(字符串角色)
{
返回(_identity!=null&&u identity.IsAuthenticated);
}
#端区
}
//System.Security.Principal.IIdentity接口的基本实现。
公共类标识:System.Security.Principal.IIdentity
{
#区域字段
私有只读int_userId;
私有只读文件已验证;
私有只读字符串\u用户名;
#端区
#区域构造函数
公众身份(FormsAuthenticationTicket formsAuthTicket)
{
如果(formsAuthTicket==null)
{
抛出新的NullReferenceException(“FormsAuthenticationTicket不能为null”);
}
if(string.IsNullOrEmpty(formsauthtticket.UserData))
{
抛出新的NullReferenceException(“FormsAuthenticationTicket.UserData不能为null或空。”);
}
string[]userData=formsauthtticket.userData.Split(新[]{“|”},StringSplitOptions.RemoveEmptyEntries);
if(userData.Length<1)
{
抛出新ArgumentOutOfRangeException(“formsAuthTicket”,userData,“userData不包含用户ID和/或站点ID”);
}
_userId=Convert.ToInt32(userData[0]);
_isAuthenticated=!FormsAuthenticate.Expired;
_userName=formsAuthTicket.Name;
}
#端区
#区域属性
公共int用户标识
{
得到
{
返回_userId;
}
}
公共字符串身份验证类型
{
得到
{
返回“表格”;
}
// 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
}
HttpContext.Current.User = principal;
HttpContext.Current.User.Identity...
<authentication mode="Forms">
<forms cookieless="UseCookies" />
</authentication>