В нашем приложении мы реализовали проверку подлинности на основе ролевых форм. Это было обработано с помощью RoleModule, где мы сохраняем данные роли в cookie,
и каждый раз, когда мы читаем данные из файла cookie и создаем экземпляр объекта IPrincipal
. Этот код выполняется методом Application_OnPostAcquireRequestState
:
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-файл ролей текущими данными основного объекта.
На нашей странице Global.asax
есть метод FormsAuthentication_OnAuthenticate
, на котором мы читаем куки, обновляем куки и обновляем
билет, если он истек. Также в этом методе мы пытаемся установить значение имени пользователя в объекте сеанса, если срок действия билета истек.
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
. Теперь, когда пользователь запрашивает страницу, он перенаправляется на страницу входа. Тем не менее
печенье все еще там. Если снова пользователь пытается запросить страницу, свойство 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, а не автоматически сгенерированные. Кроме того, я проверил идентификатор процесса и тот же для всех ошибок.