我开发了一个将在Windows Azure中托管的MVC应用程序。在开发期间,我测试本地数据库和本地用户成员资格服务。在生产环境中,应用程序可以访问SQL Azure数据库和云托管的用户成员资格服务。
有时我会使用本地计算机上仅存在 的用户帐户登录网站的本地版本。如果我忘记退出但是我的机器退出测试模式,事情就会开始中断。
我将hosts
文件设置为将应用程序URL指向127.255.0.0
,以便Azure模拟器在本地处理浏览器请求。这也意味着我的测试应用程序和生产应用程序使用相同的主机名 - 一个的cookie被视为另一个的有效cookie。
如果我登录本地系统,则会为域创建ASPXAUTH
cookie,并包含本地系统中用户的凭据。如果我忘记注销并将hosts
文件切换回正常状态(浏览器请求转到实时应用程序),它会向服务器发送相同的ASPXAUTH
cookie。
由于服务器上不存在此用户,仅在本地,因此Membership.GetUser().Email
之类的任何请求都会返回对象null异常。
理想情况下,我可以在请求的早期注入一些代码来检查用户是否存在。类似的东西:
MembershipUser user = Membership.GetUser();
if(user == null) {
FormsAuthentication.SignOut();
}
这会自动删除无效用户的ASPXAUTH
Cookie。但是我把它放在哪里?我开始查看我的控制器 - 所有这些都继承自BaseController
类,但即使将此代码放在基本控制器的构造函数中也不够早。我也查看了Global.asax
,但我不确定将此操作绑定到哪个事件最佳。
另外,我甚至不确定这是做正确事情的正确方法。如果没有,那么在仅依赖于我目前的成员资格类之前,确保身份验证cookie适用于有效用户的最佳方法是什么?
答案 0 :(得分:4)
您可以在global.aspx中处理以下事件:
public void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs args)
{
}
修改强>
在above method中,Membership.GetUser()
将返回null
,因为它从HttpContext.Current.User.Identity.Name
属性获取userName,并且在此事件中用户尚未经过身份验证。当FormsAuthenticationModule引发Authenticate时,AuthenticateRequest会调用上述方法。您可以像这样处理此事件:
public void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs args)
{
if (FormsAuthentication.CookiesSupported &&
Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
try
{
var formsAuthTicket = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value);
MembershipUser user = Membership.GetUser(formsAuthTicket.Name);
if (user == null)
{
FormsAuthentication.SignOut();
Request.Cookies[FormsAuthentication.FormsCookieName].Value = null;
}
}
catch (Exception ex)
{
//TODO:log ex
}
}
}
您还可以考虑通过在global.aspx中声明以下方法来处理{{3}}事件。
注意:在 FormsAuthentication_OnAuthenticate 事件后触发 Application_AuthenticateRequest 事件。
void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
{
MembershipUser user = Membership.GetUser();
if (user == null)
{
FormsAuthentication.SignOut();
HttpContext.Current.User = null;
}
}
}
希望这会有所帮助..
答案 1 :(得分:0)
您创建一个基本控制器,覆盖OnActionExecuting
并将代码放在那里。
让所有控制器控制器继承他。这是我所拥有的旧项目中的OnActionExecuting
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Request.IsAuthenticated)
{
if (Session[SomeKey] == null)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Account" }, { "action", "LogOff" } });
}
}
base.OnActionExecuting(filterContext);
}
我基本上检查请求是否经过身份验证,否则我会将其重定向到注销操作。 http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onactionexecuting.aspx