Сообщение: ID4243: не удалось создать SecurityToken. Токен не был найден в кеше токенов, и в контексте не было найдено ни одного файла cookie.

Мы получаем ту же ошибку, что и в этом потоке ... в нашей производственной среде. [Кэширование токена безопасности WIF

У кого-нибудь есть исправление этой ошибки? Сообщение: ID4243: не удалось создать SecurityToken. Токен не был найден в кэше токенов, и в контексте не было найдено ни одного файла cookie.

Вот некоторая информация о нашей установке:

• Мы используем встроенную платформу Windows Identity Framework с .NET Framework 4.5.1.

• Проблема почти всегда связана с переходом с RelyingParty#X на RelyingParty#Y (например, в тот момент, когда пользователь щелкает RP#Y, он ВЫХОДИТ, не запрашивая этого) — когда он снова входит в систему после этого события, он s попадает прямо на страницу, которую он просил, внутри RP#Y

• Мы используем e.SessionToken.IsReferenceMode = true; // Кэшировать на сервере, чтобы получить куки меньшего размера

• Используя IsReferenceMode = true, наш файл cookie FedAuth сохраняет «указатель» на фактический токен, который хранится в нашей базе данных.

• Мы используем собственный DatabaseSecurityTokenCache, который переопределяет функции SessionSecurityTokenCache. Используя DatabaseSecurityTokenCache вместе с IsSessionMode = true, мы дружественны к серверной ферме (но мы также гарантируем, что будем находиться на одном сервере на протяжении всего сеанса входа в систему), поэтому, если пул приложений по какой-либо причине умирает, мы можно получить токен из базы данных через DatabaseSecurityTokenCache. Я проверил это, полностью отключив IIS в середине сеанса (с помощью «net stop WAS» и снова перезапустив его с помощью «net start W3SVC», и мы все еще можем получить токен из DatabaseSecurityTokenCache). Я также пытался сделать то же самое, просто используя готовый SessionSecurityTokenCache, и это соответственно не работает (как и ожидалось).

• Срок действия токена по умолчанию составляет 20 минут (но пользователь может изменить его на 40 или 60 минут, если захочет) — он вступит в силу только при следующем входе пользователя в систему (и 90% наших пользователей просто используют 20 минут по умолчанию). минут жизни )

• Мы используем сертификат (одинаковый на всех серверах) для шифрования файла cookie FedAuth, а НЕ машинный ключ (что было бы катастрофой при использовании серверной фермы с разными машинными ключами).

• чтобы все серверы могли расшифровывать куки, которые были зашифрованы с другого сервера.

• У нас есть javascript с обратным отсчетом в RelyingParty4 и RelyingParty5 (две разные проверяющие стороны), который используется в качестве «скрипта тайм-аута» на случай, если пользователь оставит свой компьютер без присмотра... он выйдет из системы, когда токен будет готов. expire – (минус) 30 секунд (например, 20 минут – 30 секунд = 19,5 минут) с временем простоя. Это защищает нашу очень конфиденциальную банковскую информацию, поэтому, когда пользователь возвращается к своей машине, ему нужно будет снова войти в систему. например Мы также используем скользящие сеансы ([http://www.cloudidentity.com/blog/2013/05/08/sliding-sessions-for-wif-4-5/]), и когда мы скользим, время в javascript клиент также обновляется, чтобы соответствовать длине токена минус 30 секунд. Эти 30 секунд используются для того, чтобы убедиться, что сеанс все еще активен при выходе, поэтому он немного короче, чем время жизни токена/сеанса. В настоящее время мы скользим, если выполняется это условие: общее время жизни / 2 .... например. 20/2

• Мы скользим только в том случае, если с пользователем происходит какая-либо активность (например, он перемещается, выполняет какую-то работу). Мы скользим к 10+ минутам (если время жизни токена составляет 20 минут), как показано в приведенном выше примере.

• Мы несколько раз отлаживали проблему, и мы получаем следующую ошибку WIF: Исключение: System.IdentityModel.Tokens.SecurityTokenException Сообщение: ID4243: Не удалось создать SecurityToken. Токен не был найден в кэше токенов, и в контексте не было найдено ни одного файла cookie. Источник: Microsoft.IdentityModel в Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) в Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) в Microsoft.IdentityModel.Web.SessionAuthentication. ReadSessionTokenFromCookie(Byte[] sessionCookie) в Microsoft.IdentityModel.Web.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) в Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(отправитель объекта, EventArgs eventArgs) в System.Web.Stepvent.SyncApecution .HttpApplication.IExecutionStep.Execute() в System.Web.HttpApplication.ExecuteStep (шаг IExecutionStep, логическое значение и завершено синхронно)

• Мы смогли воспроизвести ошибку, используя старый файл cookie FedAuth и этот плагин: ( внимание! Мы не уверены, что это то же самое, что происходит в PROD, но, по крайней мере, это дает то же самое. ошибка в нашей системе ведения журналов) Это хорошо, но я думаю, вам следует добавить шаги о том, как мы можем изменить содержимое файла cookie FedAuth, чтобы локально решить эту проблему. это просто: взять значение файла cookie FedAuth из некоторых предыдущих сеансов (на том же компьютере! не с другого компьютера, это не сработает) и вставить его в значение файла cookie FedAuth и обновить страницу.

Плагин, используемый для изменения файла cookie, в Chrome называется «Редактировать этот файл cookie». ID4243 и RP вызывают немедленный FederatedSignout, потому что мы не можем исправить эту ситуацию.

Выписка....

Я также, вероятно, должен упомянуть, что мы серьезно отнеслись к статье Microsoft MSDN с пометкой «Важно» об IsReferenceMode и добавили ее также в наш

Событие SessionAuthenticationModule_SessionSecurityTokenCreated:

e.SessionToken.IsReferenceMode = true;

взято из MSDN:

Важный! Для работы в эталонном режиме Microsoft рекомендует предоставить обработчик события WSFederationAuthenticationModule.SessionSecurityTokenCreated в файле global.asax.cs и задать свойство SessionSecurityToken.IsReferenceMode для токена, переданного в свойстве SessionSecurityTokenCreatedEventArgs.SessionToken. Это гарантирует, что токен сеанса будет работать в эталонном режиме для каждого запроса и предпочтительнее простой установки свойства SessionAuthenticationModule.IsReferenceMode в модуле аутентификации сеанса.

Ниже приведен весь наш SessionAuthenticationModule_SessionSecurityTokenReceived, пожалуйста, изучите комментарии, которые я в него вставил... это объясняет, что все делает:

void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
    {
        if (e.SessionToken.ClaimsPrincipal != null)
        {
            DateTime now = DateTime.UtcNow;
            DateTime validTo = e.SessionToken.ValidTo;
            DateTime validFrom = e.SessionToken.ValidFrom;
            TimeSpan lifespan = new TimeSpan(validTo.Ticks - validFrom.Ticks);

            double keyEffectiveLifespan = new TimeSpan(e.SessionToken.KeyExpirationTime.Ticks - e.SessionToken.KeyEffectiveTime.Ticks).TotalMinutes;
            double halfSpan = lifespan.TotalMinutes / 2;

            if (validFrom.AddMinutes(halfSpan) < now && now < validTo)
            {
                SessionAuthenticationModule sam = sender as SessionAuthenticationModule;

                // This will ensure a re-issue of the token, with an extended lifetime, ie "slide". Id deletes the current token from our databasetoken cache (with overriden Remove of the SessionSecurityTokenCache ) and writes a new one into the cache with the overriden AddOrUpdate of the SessionSecurityTokenCache. 
                // it will also write the token back into the cookie ( just the pointer to the cookie, because it's stored in database-cache ) because the IsReferenceMode = True is set
                e.ReissueCookie = true; // Will force the DatabaseSecurityTokenCache'ið to clean up the cache with this, handler.Configuration.Caches.SessionSecurityTokenCache.Remove(key); internally in WIF's SessioAuthenticationModule

                e.SessionToken = sam.CreateSessionSecurityToken(
                    e.SessionToken.ClaimsPrincipal,
                    e.SessionToken.Context,
                    now,
                    now.AddMinutes(lifespan.TotalMinutes),
                    false); // Make persistent, þannig að kakan lifir EKKI af browser-close / tab-lokun:
                {
                    e.SessionToken.IsReferenceMode = true; // Cache on server
                }

                // Not needed, because if ReissueCookie = true;  is set, it WILL to a WriteSessionTokenToCookie internally in WIF
                //FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(e.SessionToken); // <---- er þetta e.t.v. bara það sem við þurfum ? Nei, á ekki að þurfa, er gert þegar tóki er búinn til með CreateSessionSecurityToken
            }
            else if (validTo < now)
            {
                // Fix
                // http://blogs.planbsoftware.co.nz/?p=521                    

                var sessionAuthenticationModule = (SessionAuthenticationModule)sender;
                sessionAuthenticationModule.DeleteSessionTokenCookie(); // <--- is this really needed like the article says ? http://blogs.planbsoftware.co.nz/?p=521
                e.Cancel = true; // This will allow a silent-login if the STS cookie is still valid, e.g. switching between RP's where we're switching from an active RP to a RP which has it's cookie outdated, but the STS's session is still alive. We don't want to prompt the user for a new login, beucase the STS session is still OK!
            }
    }

person Lord02    schedule 17.12.2013    source источник
comment
Подобно этой проблеме здесь, все еще нерешенной: stackoverflow.com /questions/9793900/wif-security-token-caching/   -  person Lord02    schedule 17.12.2013
comment
Может ли кто-нибудь изменить мою учетную запись, чтобы я мог пометить свой вопрос как отвеченный - похоже, моя учетная запись не может этого сделать!   -  person Lord02    schedule 02.09.2014
comment
Lord02: где твой ответ? Вам нужно ввести ответ в разделе ответов. Вы не можете пометить вопрос как отвеченный без ответа в разделе ответов.   -  person user20358    schedule 15.12.2014
comment
user20358: Ответ находится в самом посте, четко помеченном обновлением, как это: ---------- ОБНОВЛЕНИЕ, вот как я исправил проблему -----------   -  person Lord02    schedule 03.03.2015
comment
Я переместил ответ из поста в реальный ответ   -  person thijs    schedule 15.09.2015


Ответы (2)


этот пост помог мне, так что он может помочь вам и другим людям, у которых есть такая ошибка.

void Application_OnError()
{
  var ex = Context.Error;
  if (ex is SecurityTokenException){
     Context.ClearError();
     if (FederatedAuthentication.SessionAuthenticationModule != null){
         FederatedAuthentication.SessionAuthenticationModule.SignOut();
     }
   Response.Redirect("~/");
  }
}

Из этого ссылка.

Надеюсь, это было полезно!

person SeeSharp    schedule 07.05.2016

---------- ОБНОВЛЕНИЕ. Вот как Lord02 исправил проблему ------------

Проблема заключалась в том, что когда пользователи входят с устаревшими файлами cookie (из предыдущего сеанса, т.е. если они НЕ вышли из нашей системы... а вместо этого просто закрыли вкладку), а затем снова вошли в систему, наш файл cookie, который был в SessionMode = true ... попытался перейти к DatabaseTokenCache, чтобы ПОЛУЧИТЬ весь токен из базы данных, но, как я уже сказал, наш процесс SSIS удаляет все токены, которые старше 12 часов (устаревшие токены!), поэтому у нас нет множества потерянных токены, которые устарели в нашей базе данных и непригодны для использования... просто занимают место в нашей базе данных. Таким образом, после того, как это удаление будет выполнено, каждую ночь функция DatabaseTokenCache GET не будет возвращать действительный токен ... и пользователь вышел из системы из-за: ID4243: не удалось создать SecurityToken. Токен не был найден в кэше токенов, и в контексте не было найдено ни одного файла cookie.

Поэтому вместо того, чтобы НЕ удалять токены внутри нашей базы данных, я создал специальный обработчик, который перехватывает эту ошибку на сайте RP... и перенаправляет пользователя обратно в STS, который затем создаст новый токен и запишет его. в DatabaseTokenCacheStore, как показано ниже

Исключение с ID4243 выдается, когда файл cookie установлен как «эталонный режим» И токен отсутствует в кеше — я могу подтвердить, что это сделано по замыслу, а также по замыслу WIF не перенаправляет вызов к STS (в начать процесс аутентификации заново)

Чтобы преодолеть эту проблему, я перехватываю это исключение и правильно реагирую. Я перенаправляюсь к эмитенту, если эта ошибка появляется внутри customSessionAuthModule, который я создал для этого:

public class CustomSessionAuthenticationModule : SessionAuthenticationModule
{
    protected override void OnAuthenticateRequest(object sender, EventArgs eventArgs)
    {
        try
        {
            base.OnAuthenticateRequest(sender, eventArgs);
        }
        catch (SecurityTokenException exc)
        {
            // ID4243: Could not create a SecurityToken. A token was not found in the token cache and no cookie was found in the context.
            if (exc.Message.IndexOf("ID4243", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                // Returning directly without setting any token will cause the FederationAuthenticationModule
                // to redirect back to the token issuer.
                return;
            }
            else
            {
                throw;
            }
        }
    }
} 
person Community    schedule 15.09.2015