如何在请求的早期使无效的身份验证cookie失效?

时间:2012-05-02 18:50:42

标签: asp.net-mvc cookies forms-authentication .aspxauth

方案

我开发了一个将在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适用于有效用户的最佳方法是什么?

2 个答案:

答案 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