1

В нашем приложении мы реализовали аутентификацию на основе ролей. Это обрабатывается с помощью 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, а не автоматически сгенерированный. Кроме того, я проверил идентификатор процесса и его то же самое для всех ошибок.

ответ

1

Я, наконец, решил проблему. Случилось то, что при истечении билета FormsAuthentication FormsAuthentication_OnAuthenticate не смог установить контекст.Пользовательский объект, как указано в MSDN documentation для Authenticate события:

Если вы не укажете значение для свойства пользователя во время FormsAuthentication_OnAuthenticate событие, личность поставляется билет аутентификации формы в куки или URL является используемый.

Причина в том, что я не устанавливаю ticket.Name с именем пользователя. Это пустая строка. Следовательно, может быть, событие Authenticate не могло получить идентификатор пользователя и создать экземпляр FormsIdentity. В качестве решения, когда я обновляю просроченный билет, я также создаю объект GenericIdentity, а затем использую его для установки context.User.

IIdentity identity = new GenericIdentity(username, "Forms"); 
context.User = new CustomPrincipal(identity); 
Смежные вопросы