MVC中的两步认证?

时间:2011-03-25 20:23:44

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

我们有一个MVC应用程序,它有一个自定义表单身份验证视图/控制器。控制器将验证事物,然后执行FormsAuthentication.RedirectFromLoginPage调用。

在Global.asax的这一点上,我们将收到一个Application_OnAuthenticateRequest调用,我们将从中获取他们的Context.User信息并再次调用以收集与此帐户相关的信息,然后我们将其存储在他们的Context.User& amp ; System.Threading.Thread.CurrentPrincipal。我们还对这些信息进行了一些缓存,因为在我们的系统中检索我们需要的东西是昂贵的,这导致缓存失效&重新检索此信息。

此时似乎有点奇怪,我们已将这些分成单独的调用。我几乎想知道登录控制器是否应该收集细节作为其身份验证检查的一部分并存储它们。然后,Application_OnAuthenticateRequest只会担心是否需要使缓存失效并重新检索用户详细信息。

或许还有其他一些方法可以解决这个问题,我甚至不知道......?

1 个答案:

答案 0 :(得分:2)

您可以利用RedirectToRouteResult和自定义缓存更新ActionFilter在MVC中执行您想要的操作。这称为PRG(Post-Redirect-Get)模式。你实际上已经这样做了,但它有点困惑,因为你所做的是经典的ASP.NET服务方式和MVC服务方式之间的交叉。您的初始方法没有任何问题(只要它正常工作),但是要做同样的事情,并且能够更好地控制和理解它在您可以执行的操作方案中的工作原理:

public class AuthenticationController :Controller
{
    [HttpPost]
    public RedirectToRouteResult Login(string username, string password)
    {
        //authenticate user
        //store authentication info in TempData like
        bool authenticated = true|false; // do your testing
        if(authenticated)
        {
            TempData["MustUpdateCache"] = true | false;
            return RedirectToAction("LoginSuccess", new{userId = membershipUser.UserId});                
        }
        else
        {
            TempData["MustUpdateCache"] = true | false;
            return RedirectToAction("Login");
        }
    }

    [HttpGet, UpdateCache]
    public ActionResult LoginSuccess(Guid userId, string url)
    {
        HttpContext.User = LoadUser(userId);
        return View();
    }

    [HttpGet, UpdateCache]
    public ViewResult Login()
    {
        return View();
    }

}
public class UpdateCacheAttribute:ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var tempData = filterContext.Controller.TempData;
        if (tempData.ContainsKey("MustUpdateCache") && (bool)tempData["MustUpdateCache"])
        {
            UpdateCache(filterContext);
        }
    }

    void UpdateCache(ControllerContext controllerContext)
    {
        //update your cache here
    }
}