В нашем приложении мы реализовали аутентификацию на основе ролей. Это обрабатывается с помощью RoleModule, где мы сохраняем данные роли в cookie, и каждый раз, когда мы считываем данные из файла cookie и создаем объект IPrincipal
. Этот код выполняется в методе Application_OnPostAcquireRequestState
:Повторно инициализировать context.User после FormsAuthenticationTicket timeout
HttpApplication application = source as HttpApplication;
HttpContext context = application.Context;
if (context.User.Identity.IsAuthenticated &&
(!Roles.CookieRequireSSL || context.Request.IsSecureConnection))
{
//Read the roles data from the Roles cookie..
context.User = new CustomPrincipal(context.User.Identity, cookieValue);
Thread.CurrentPrincipal = context.User;
}
Это инициализирует context.User
объект. Каждый раз, когда запрос поступает на сервер, пользователь аутентифицируется с использованием вышеуказанного потока. В Application_EndRequest
мы обновляем cookie Роли с данными текущего основного объекта.
Существует FormsAuthentication_OnAuthenticate
метода в нашей Global.asax
страницы, в которой мы читаем кук, обнови кук, и обновить билет, если он истек. Кроме того, в этом методе мы пытаемся установить значение имени пользователя в объекте сеанса, если срок действия билета истек.
FormsAuthentication oldTicket = FormsAuthentication.Decrypt(context.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
if(oldTicket != null)
{
if(oldTicket.Expired)
{
try
{
HttpContext.Current.Session["UserName"] = userName;
}
catch
{
//Log error.
}
FormsAuthentication newTicket = new FormsAuthenticationTicket(oldTicket.Version, oldTicket.Name, DateTime.Now,
DateTime.Now.AddMinutes(30), oldTicket.IsPersistent, oldTicket.UserData);
string encryptedTicket = FormsAuthentication.Encrypt(newTicket);
HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
if (isPersistent)
{
httpCookie.Expires = DateTime.Now.AddMinutes(300);
}
}
Здесь установка наших форм в web.config:
<forms defaultUrl="Default.aspx" domain="" loginUrl="Login.aspx" name=".ASPXFORMSAUTH" timeout="20" slidingExpiration="true" />
Тайм-аут сеанса 20 минут.
Вопрос: Если пользователь находится в режиме ожидания в течение более чем 30 минут (что продолжительность времени обновления билета FormsAuth), значение context.User.Identity.IsAuthenticated
в модуль роли false
и context.User
устанавливаются как NULL
.. Теперь, когда пользователь запрашивает страницу, он перенаправляется на страницу входа в систему. Тем не менее, cookie все еще существует. Если снова пользователь пытается запросить страницу, то для свойства context.User.IsAuthenticated
установлено значение true
, и пользователь отправляется на соответствующую страницу . Кроме того, в методе FormsAuthentication_OnAuthenticate
, когда я пытаюсь установить значение сеанса, он выдает ошибку, поскольку объект сеанса - NULL
.
Что я хочу достичь здесь, так это то, что в случае постоянного файла cookie после истечения времени ожидания авторизации пользователь не должен выходить из системы, то есть пользователь должен быть повторно аутентифицирован.
Как я могу это достичь? Если я не ошибаюсь, установка context.User
должна решить эту задачу, но как мне ее решить?
Дополнительная информация:
После того, как билет истекает, и я пытаюсь запросить страницу, просмотра событий показывает сообщение об ошибке:
Event code: 4005
Event message: Forms authentication failed for the request. Reason: The ticket supplied has expired.
Event time: 08-02-2012 20:02:05
Event time (UTC): 08-02-2012 14:32:05
Event ID: 048e3238ade94fd6a7289bac36d130ef
Event sequence: 76
Event occurrence: 2
Event detail code: 50202
Process information:
Process ID: 21692
Process name: w3wp.exe
Account name: IIS APPPOOL\ASP.NET v4.0 Classic
Я использую стандартные ключевые настройки машины, сохраненные в web.config, а не автоматически сгенерированный. Кроме того, я проверил идентификатор процесса и его то же самое для всех ошибок.