Срок действия FormsAuthentication действительно состоит из двух частей:
- истечение срока действия билета аутентификации
- истечение срока действия куки, содержащего билет
Если вы хотите отключить истечение срока действия и возобновить билет вручную, вам необходимо обновить билет и вернуть новый файл cookie аутентификации в браузер.
Массив Response.Cookies
пуст, если вы (или другой код) не добавите к нему что-либо. Он предназначен только для добавления файлов cookie, которые являются новыми или чье содержимое / срок действия / что-либо изменило . Пустой Response.Cookies
означает только то, что ничего не изменилось - браузер сохранит файлы cookie, которые у него уже есть (до истечения срока их действия), и все равно отправит их при следующем запросе.
Стандартный способ изменения содержимого или истечения срока действия файлов cookie заключается в получении cookie-файла, отправленного браузером (с Request.Cookies
), его изменении, а затем добавлении в Response.Cookies
.
Вот пример кода для ручного обновления файла cookie для аутентификации (отказ от ответственности: тщательно протестируйте и подумайте):
// You could also get the ticket from
// Request.Cookies using FormsAuthentication.Decode
FormsIdentity identity = HttpContext.Current.User.Identity as FormsIdentity;
if (identity == null) return; // User isn't authenticated
// Renew the ticket - you could also create a new ticket manually
// (see * below for an example), if you want to get rid of ASP.NET's
// rather confusing renew-if-old policy:
FormsAuthenticationTicket ticket =
FormsAuthentication.RenewTicketIfOld(identity.Ticket);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
encryptedTicket
);
// Better keep this (see * below):
cookie.Secure = FormsAuthentication.RequireSSL;
cookie.HttpOnly = true;
// Isn't a security issue if this is set too long - the ticket contained
// within will still expire after the set time, and the server will timeout
// the auth session on the next request.
// But let's just keep cookie and ticket in sync:
cookie.Expire = ticket.Expiration;
// Add cookie to response to send the changes to the browser:
HttpContext.Current.Response.Cookies.Add(cookie);
Обратите внимание, что FormsAuthentication.RenewTicketIfOld()
не всегда будет продлевать билет. Он будет продлен только если осталось менее половины времени истечения. То есть, если ваше время ожидания в web.config установлено на 20 минут, а RenewTicketIfOld вызывается через 7 минут после создания заявки, заявка не будет продлена, и останется еще 13 минут. Если он вызывается после, например, 12 минут, он будет продлен до 20 минут.
Причина этого заключается в том, что RenewTicketIfOld используется для параметра slideExpiration при каждом запросе и, таким образом, отправляет новый файл cookie при каждом запросе (для сброса срока действия до [timeout] минут). Только отправка нового cookie-файла с билетом обратно по истечении хотя бы половины времени избавляет от большого количества ненужных файлов cookie - за счет того, что он вводит в заблуждение разработчиков и конечных пользователей.
*) На cookie.Secure
см. Hanselman: Weird Timeouts - это просто гарантирует, что, если RequireSSL установлен в web.config, cookie будет учитывать это, что позволяет избежать многих кошмаров отладки, если вы переместить сайт на SSL.