Двухэтапная аутентификация в MVC? - PullRequest
2 голосов
/ 25 марта 2011

У нас есть приложение MVC, которое имеет настраиваемый вид проверки подлинности форм / контроллер. Контроллер проверяет вещи и затем выполняет вызов FormsAuthentication.RedirectFromLoginPage.

В этот момент в Global.asax мы получим вызов Application_OnAuthenticateRequest, откуда мы получим их Context.User информацию и сделаем еще один вызов, чтобы собрать информацию, относящуюся к этой учетной записи, которую мы затем сохраним в их Context.User & System.Threading.Thread.CurrentPrincipal. Мы также делаем небольшое кеширование этой информации, так как в нашей системе получение того, что нам нужно, обходится дорого, что приводит к аннулированию кэша и повторному поиску этой информации.

Кажется немного странным, что мы разделили их на отдельные вызовы. Я почти задаюсь вопросом, не должен ли Контроллер входа собирать детали как часть своей проверки подлинности и сохранять их. Тогда Application_OnAuthenticateRequest может беспокоиться только о том, нужно ли сделать кэш недействительным, а данные пользователей повторно получены.

Или, может быть, есть какой-то другой способ справиться с этим, о котором я даже не знаю ...?

1 Ответ

2 голосов
/ 26 марта 2011

Вы можете делать то, что вы хотите в MVC, используя RedirectToRouteResult и настраиваемое обновление кэша ActionFilter.Это называется паттерном 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
    }
}
...