当用户登录 ASP.net 网站时,有没有办法收到通知?
注意:用户无需访问"登录页面"即可登录。如果"记住我"cookie存在,他们可以点击任意页面并登录。
当用户登录时,我想获取一些与会话相关的信息。
注意:有
Login.LoggedIn
事件。问题是该控件并非在每个页面上都存在;它出现在(Login.aspx
)上的一个页面不会调用OnLoggedIn
事件。
与Global.asax
具有全局"会话启动"通知的方式相同:
void Session_Start(object sender, EventArgs e)
{
}
我假设某处有一个用户登录通知:
void LoggedIn(object sender, EventArgs e)
{
}
奖金阅读
- 登录
- 页面上的登录事件 ASP.NET
- 登录时运行自定义代码
- MDSN Logon.OnLoggedIn 事件
- 如果设置了"记住我",如何更新上次登录日期?
我认为你没有一个独特的地方来做到这一点。在我的情况下(MVC + log4net),我使用这个:
-
Global.asax
,我使用预先存在的cookie检查经过身份验证的用户。protected void Session_Start() { string ip = HttpContext.Current.Request.UserHostAddress; log.InfoFormat("Starting session: {0} from {1}.",Session.SessionID, ip); if ((HttpContext.Current != null) && (HttpContext.Current.User != null) && (HttpContext.Current.User.Identity.IsAuthenticated) ) { string user = HttpContext.Current.User.Identity.Name; string type = "Cookie"; log.InfoFormat("User {0} logged in with {1}.", user, type); } }
-
在我的帐户控制器中,我检查本地登录(我使用的是 MVC4 中的 Internet 应用程序模板,但如果您使用的是 Web 表单,则可以在
Login.OnLoggedIn
中执行此操作)[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult Login(LoginModel model, string returnUrl) { if (ModelState.IsValid && WebSecurity.Login(model.EMail, model.Password, persistCookie: model.RememberMe)) { string user = model.EMail; string type = "Forms"; log.InfoFormat("User {0} logged in with {1}.", user, type); return RedirectToLocal(returnUrl); } // If we got this far, something failed, redisplay form ModelState.AddModelError("", "The user name or password provided is incorrect."); log.ErrorFormat("Bad password or user name. User={0}", model.EMail, model.Password); return View(model); }
-
但是我也需要检查OAuth登录,如下所示:
[AllowAnonymous] public ActionResult ExternalLoginCallback(string returnUrl) { AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl })); if (!result.IsSuccessful) { log.Debug("External login failure."); return RedirectToAction("ExternalLoginFailure"); } if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false)) { log.InfoFormat("User {0} logged in with External {1} login. External UserID = {2}", Membership.GetUser(OAuthWebSecurity.GetUserName(result.Provider, result.ProviderUserId)).UserName, result.Provider, result.ProviderUserId); return RedirectToLocal(returnUrl); } ... }
您可以在global.asax上进行检查Application_AuthenticateRequest
,这是您可以检查请求是否与您的会话数据一起登录的地方,并决定会话数据是否需要像您所说的那样初始化。
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
// check for logged in or not
if (null != authCookie)
{
// is logged in... check if the session needs init
}
}
或相同的结果
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// check for logged in or not
if(HttpContext.Current.User != null &&
HttpContext.Current.User.Identity != null
&& HttpContext.Current.User.Identity.IsAuthenticated)
{
// is logged in... check if the session needs init
}
}
以下两个位置调用代码:Login
控件中的OnLoggedIn
事件以及会话启动时(使用 Global.asax 中的 Session_Start
事件),因为这将是用户数据的第一个请求。在那里,您可以检查用户是否已记录,如果是,请执行所需的操作。
虽然从技术上讲,登录与身份验证相同,但我对此有不同的心理模型。
在我看来,以下三件事是不同的问题:
- 用户具有/获取会话
- 用户已通过身份验证
- 用户已登录
对我来说,其中最后一个意味着:"已为用户创建了会话,用户已通过身份验证,并且已为经过身份验证的用户初始化会话"。
使用此模型,用户可以在以下情况下登录:
- 用户在登录页面上登录,并且预先存在的会话是使用必要的用户数据初始化
- 经过预身份验证的用户访问站点,并且新会话是为他/她创建和初始化
同样,当用户的初始化会话被销毁时,用户将注销。
使用此模型将意味着:
- 您可以识别用户何时在
Login.OnLoggedIn
事件或Global.asax
Session_Start
事件中"登录"。当然,会话启动事件也会针对未经身份验证的用户触发,因此您需要在事件触发时验证用户是否已通过身份验证。 - 您可以通过显式注销或在 Global.asax 的
Session_End
事件中取消正确初始化的会话来可靠地判断用户何时"注销"。我说有点可靠,因为我认为当应用程序池回收或在崩溃中死亡时,Session_End事件不一定会被触发。虽然我还没有测试过这个,所以我可能是错的。 - 用户可以同时多次"登录"。至少在IE中,您可以从"文件"菜单启动"新会话"。这将启动一个新的IE,该IE不会与任何预先存在的IE窗口共享会话cookie。这意味着当用户访问站点时,服务器将创建一个新会话,并且根据所使用的自编机制,这可能意味着他/她也必须再次进行身份验证。
它不会让您开箱即用地"列出所有当前登录的用户"。我认为,您将需要创建自己的方法来跟踪它。这对我来说或多或少很难做到。特别是在应用程序在某种负载平衡环境中运行时,获取所有当前用户的列表可能会很棘手。