由于我不想讨论的原因,我需要为我的应用程序创建一个自定义身份验证系统。我只是在审查系统,如果我的解决方案是线程安全的,我有一些疑问。我的目标是创建一个解决方案,允许我的应用程序对用户进行一次身份验证,并且用户身份验证信息将由所使用的所有母版页,页面,类,用户控件等共享。 (但不能在用户之间共享相同的信息)
这是我的设置:
PageHttpModule.cs - 它作为httpModule添加到web.config。
public class PageHttpModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.AuthenticateRequest += new EventHandler(OnAuthenticateRequest);
}
public void OnAuthenticateRequest(Object s, EventArgs e)
{
CurrentUser.Initialize();
}
public void Dispose() { }
}
CurrentUser.cs
public static class CurrentUser
{
public static bool IsAuthenticated { get; private set; }
public static string Email {get; set;}
public static string RealName {get; set;
public static string UserId {get; set;}
public static void Initialize()
{
CurrentUser.AuthenticateUser();
}
Note: this is a scaled down version of my authentication code.
public static void AuthenticateUser()
{
UserAuthentication user = new UserAuthentication();
user.AuthenticateUser();
if (user.IsAuthenticated)
{
CurrentUser.IsAuthenticated = true;
CurrentUser.UserId = user.UserId;
CurrentUser.Email = user.Email;
CurrentUser.RealName = user.RealName;
}
}
}
UserAuthentication.cs
public class UserAuthentication
{
public string Email { get; set; }
public string RealName { get; set; }
public string UserId { get; set; }
public bool IsAuthenticated { get; private set; }
public UserAuthentication()
{
IsAuthenticated = false;
Email = String.Empty;
RealName = String.Empty;
UserId = String.Empty;
}
public void AuthenticateUser()
{
//do some logic here.. if the user is ok then
IsAuthenticated = true
Email = address from db
UserId = userid from db;
Realname = name from db;
}
}
我已经在3种不同的浏览器之间进行了测试,它似乎运行良好,但我仍然在学习,并且不想犯错误。
如果我的逻辑是完全错误的,那么我应该怎么做呢?所以我不必直接在每个页面上进行用户查找?
答案 0 :(得分:3)
不,这不是线程安全的。对于生活在单独进程或AppDomains中的应用程序的实例,这将很好。但是如果你的ASP.NET服务器要使用线程一次服务多个请求,那么如果两个人同时尝试使用该应用程序,你将会产生一些非常糟糕的副作用。
答案 1 :(得分:1)
为什么不按照微软推荐的方式去做呢?
http://msdn.microsoft.com/en-us/library/9wff0kyh.aspx
我已经通过这种方式完成了自定义身份验证,并且运行正常。
这是另一个应该证明有用的链接:
http://blogs.msdn.com/b/ncl/archive/2009/05/05/custom-http-authentication-schemes.aspx
答案 2 :(得分:1)
在Init
方法中,HttpApplication
参数描述为:
一个HttpApplication,提供对ASP.NET应用程序中所有应用程序对象通用的方法,属性和事件的访问
这里的关键是应用程序的生命周期中有一个PageHttpModule
,应用程序生命周期中存在的所有静态对象都将共享这些变量。
但是...... CurrentUser
的生命周期仅在OnAuthenticateRequest
事件的范围内,除非某些其他引用使对象保持活动状态。如果它是PageHttpModule
成员级变量,那么您会遇到一些您会立即注意到的问题。但是,在您的情况下,只要您没有多次同时处理OnAuthenticateRequest
电话,您就可以正常工作。
你的问题的答案是否定的,你不能保证是线程安全的。如果两个身份验证请求同时进入,则无法保证在另一个事件开始之前完成一个事件,在这种情况下,当第二个用户确实是第一个登录的用户时,第二个用户可以显示身份验证。
的更新强>
我认为问题的一部分来自于对AuthenticateRequest
的误解......当调用此事件时,用户已经通过Windows或Forms身份验证进行了身份验证...您刚收到通知它发生了。实际上,属性User.Identity.IsAuthenticated
已经设置(我相信即使用户验证失败,此事件也会触发,但我不会在没有仔细检查的情况下发誓)。
如果我了解您的目标,那么您真的想要编写自己的自定义成员资格提供程序。如果采用这种方法,您将获得内置身份验证的所有好处......所有与身份验证相关的标准属性都将被设置和访问,并将以您希望的方式与用户的会话隔离。 / p>
编写自定义提供程序不是一件小事,但它是可行的,您应该能够重用当前用于类的许多逻辑和代码。
尝试完全重写认证机制将会遇到痛苦,复杂的箍。
一些链接:
http://www.devx.com/asp/Article/29256/0/page/3
http://www.codeproject.com/KB/aspnet/WSSecurityProvider.aspx
http://msdn.microsoft.com/en-us/library/f1kyba5e%28v=VS.90%29.aspx
您必须实现的属性可能看起来令人生畏,但除非您需要特定功能(例如ResetPassword),否则您只需抛出NotImplementedException
。仅编码您将使用的内容。
答案 3 :(得分:0)
你用IHttpModule做的事情似乎是解决这类问题的好方法。 microsoft所述的http模块的目的之一是启用任何类型的特殊身份验证。当http模块初始化时,它对新请求使用相同的实例。由于你没有任何全局变量,我不太确定如何解决你的线程安全问题。看起来你正在阅读一些数据,所以请详细说明!