Как аннулировать неверный файл 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