如何在请求的早期使错误的身份验证 Cookie 失效



>场景

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

您可以在全局.aspx中处理以下事件:

public void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs args)
{ 
}

编辑:

在上面的方法中,Membership.GetUser()将返回 null ,因为它从HttpContext.Current.User.Identity.Name属性中获取用户名,在这种情况下,用户尚未经过身份验证。上述方法由 FormsAuthenticationModule 在引发 Authenticate 偶数时调用。您可以像这样处理此事件:

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
        }
    }
}

还可以考虑通过在全局.aspx中声明以下方法来处理 AuthenticateRequest 事件。

注意:Application_AuthenticateRequest事件在FormsAuthentication_OnAuthenticate事件之后触发。

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;
        }
    }            
}

希望这有帮助..

创建一个覆盖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

最新更新