Как аннулировать неверный файл cookie для аутентификации в начале запроса?

сценарий

Я разрабатываю приложение MVC, которое будет размещено в Windows Azure. Во время разработки я тестировал локальную базу данных и службу членства локальных пользователей. В работе приложение использует базу данных SQL Azure и службу членства пользователей в облаке.

Иногда я захожу на локальную версию сайта с учетной записью, которая существует только на моем локальном компьютере. Если я забуду выйти из системы, но выключу машину из тестового режима, все начнет ломаться.

Эта проблема

Я установил свой hosts файл для указания URL моего приложения на 127.255.0.0 чтобы запросы браузера обрабатывались эмулятором Azure локально. Это также означает, что мое тестовое приложение и производственное приложение используют одно и то же имя хоста - куки для одного рассматриваются как действительные куки для другого.

Если я войду в свою локальную систему, 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 ответа

Решение

Вы можете обработать следующее событие в вашем global.aspx:

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

РЕДАКТИРОВАТЬ:

В вышеуказанном методеMembership.GetUser() вернусь null, поскольку он принимает имя пользователя из HttpContext.Current.User.Identity.Name свойство и в этом случае пользователь еще не прошел аутентификацию. Вышеуказанный метод вызывается FormsAuthenticationModule, когда он вызывает Authenticate even. Вы можете обработать это событие так:

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

Вы также можете рассмотреть возможность обработки события AuthenticateRequest, объявив метод ниже в global.aspx.

ПРИМЕЧАНИЕ. Событие 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

Другие вопросы по тегам