消息:ID4243:无法创建SecurityToken.在令牌缓存中未找到令牌,并且在上下文中未找到Cookie [英] Message: ID4243: Could not create a SecurityToken. A token was not found in the token cache and no cookie was found in the context

查看:198
本文介绍了消息:ID4243:无法创建SecurityToken.在令牌缓存中未找到令牌,并且在上下文中未找到Cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在生产环境中,我们得到与该线程完全相同的错误. [ WIF安全令牌缓存

We're getting the exact same error as in this thread ... in our production environment. [WIF Security Token Caching

有人可以解决此错误吗? 消息:ID4243:无法创建SecurityToken.在令牌缓存中未找到令牌,并且在上下文中未找到Cookie.

Does anybody have a fix to this error ? Message: ID4243: Could not create a SecurityToken. A token was not found in the token cache and no cookie was found in the context.

以下是有关我们的设置的信息:

Here is some info about our setup:

•我们正在将内置的Windows Identity Framework与.NET Framework 4.5.1一起使用

• We‘re using built-in Windows Identity Framework with .NET Framework 4.5.1

•问题几乎总是与从RelyingParty#X更改为RelyingParty#Y有关(例如,在用户单击而未要求退出的RP#Y时)–在此事件后再次登录时,他就直接转到了所要的页面,位于RP#Y

• The problem is almost always associated with changing from RelyingParty#X over to RelyingParty#Y ( e.g. the moment user clicks the RP#Y he‘s SIGNED OUT without asking for it ) – when he logs in again after this event, he‘s taken right to the page he was asking for, inside RP#Y

•我们正在使用e.SessionToken.IsReferenceMode = true;//在服务器上缓存,以获取较小的Cookie

• We‘re using e.SessionToken.IsReferenceMode = true; // Cache on server, to get a smaller cookie

•通过使用IsReferenceMode = true,我们的FedAuth cookie将指针"存储到存储在数据库中的实际令牌

• By using IsReferenceMode = true, our FedAuth cookie stores a „pointer" to the actual Token which is stored inside our database

•我们正在使用我们自己的DatabaseSecurityTokenCache,它将覆盖SessionSecurityTokenCache中的功能.通过将DatabaseSecurityTokenCache与IsSessionMode = true一起使用,我们可以实现服务器场友好(但也可以确保通过所有登录会话都位于同一服务器内),因此,如果由于某种原因导致应用程序池死亡,我们能够通过DatabaseSecurityTokenCache从数据库获取令牌.我已经通过在会话中间完全杀死IIS(使用"net stop WAS"并使用"net start W3SVC"再次将其重新启动来验证了这一点,我们仍然能够从DatabaseSecurityTokenCache获取令牌).我也尝试过通过简单地使用现成的SessionSecurityTokenCache来做同样的事情,这将相应地失败(如预期的那样)

• We‘re using our own DatabaseSecurityTokenCache which is overriding the functions in SessionSecurityTokenCache. By using the the DatabaseSecurityTokenCache alongside the IsSessionMode = true, we‘re server-farm-friendly ( but we‘re also guaranteed to be within the same server through all our login-session ) so if the application pool for some reason dies, we‘re able to get the token from database through the DatabaseSecurityTokenCache. I‘ve verified this by completely killing IIS in the middle of a session ( with „net stop WAS" and the restart it again with „net start W3SVC" and we‘re still able to get the Token from the DatabaseSecurityTokenCache ). I‘ve also tried doing the same by simply using the out-of-the-box SessionSecurityTokenCache and that will fail respectivly ( as expected )

•默认令牌寿命为20分钟(但用户可以根据需要将其更改为40或60分钟)–仅在用户下次登录时有效(我们90%的用户正在使用默认的20分钟有效期)

• Default token lifetime is 20 minutes ( but the user can change it to 40 or 60 minutes if he wants to ) – that will only be effective the next time the user logs in ( and 90% of our user are just using the default 20 minutes lifetime )

•我们正在使用证书(在所有服务器上都相同)对FedAuth cookie进行加密,而不是对机器密钥进行加密(如果使用具有不同机器密钥的服务器场,这将是灾难性的)

• We‘re using a certificate (same on all servers) to encrypt the FedAuth cookie, NOT a machine-key ( which would be catastrophic if using server-farm, with different machine-keys )

•,因此所有服务器都可以解密从另一台服务器加密的cookie.

• so all the servers can decrypt cookies, which were encrypted from another server.

•我们在RelyingParty4和RelyingParty5(两个不同的依赖方)中都有一个带有倒数计时的javascript,如果用户无人看管时将其用作超时脚本" ...当令牌释放时,他将被注销即将到期–(减去)30秒(例如20分钟– 30秒= 19,5分钟),并具有空闲时间.这可以保护我们非常敏感的银行信息,因此,当用户返回其计算机时,他将需要再次登录.例如我们还在使用滑动会话([

• We have a javascript with a countdown in our RelyingParty4 and RelyingParty5 ( two different relying parties ) which is used as a „timeout script" in case the user leaves his computer unattended ... he will be signed out when the token is about to expire – (minus) 30 seconds ( e.g. 20 minutes – 30 sec = 19,5 minutes ) with idle time. This is protect our very sensitive banking information, so when the user comes back to his machine he will need to login again. e.g. We‘re also using sliding sessions ([http://www.cloudidentity.com/blog/2013/05/08/sliding-sessions-for-wif-4-5/]) and when we slide, the timing in the javascript of the client is also updated as well, to match the length of the token minus 30 seconds. These 30 seconds are used to make sure that the session is still alive when signing out, so it‘s a little bit shorter than the lifetime of the token/session. We currently sliding if this condition is met: total lifetime / 2 .... e.g. 20 / 2

•如果用户正在进行任何活动(即他在四处走动,做一些工作),我们只会滑动.如上例所示,我们的分钟数为10分钟(如果令牌寿命为20分钟)

• We‘re only sliding if there‘s any activity going on with the user ( i.e. he‘s moving around, doing some work ). We're sliding in minute10+ (if token lifetime is 20minuts) as the example above shows

•我们已多次调试问题,这是我们收到的WIF错误:异常:System.IdentityModel.Tokens.SecurityTokenException消息:ID4243:无法创建SecurityToken.在令牌缓存中未找到令牌,并且在上下文中未找到cookie.来源:Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader读取器,SecurityTokenResolver tokenResolver)处的Microsoft.IdentityModel.Microsoft.IdentityModel.Web.SessionAuthenticationModule处的Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte []令牌,SecurityTokenResolver令牌Resolver). Microsoft.IdentityModel.Web.SessionAuthenticationModule.Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(Object sender,EventArgs eventArgs)的System.Web.HttpApplication.SyncEventExecutionStep.上的ReadSessionTokenFromCookie(Byte [] sessionCookie). System.Web.HttpApplication.ExecuteStep处的Web.HttpApplication.IExecutionStep.Execute()(IExecutionStep步骤,布尔值和已完成同步)

• We‘ve debugged the problem multiple times and this is the WIF error we‘re getting: Exception: System.IdentityModel.Tokens.SecurityTokenException Message: ID4243: Could not create a SecurityToken. A token was not found in the token cache and no cookie was found in the context. Source: Microsoft.IdentityModel at Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) at Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) at Microsoft.IdentityModel.Web.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) at Microsoft.IdentityModel.Web.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) at Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

•我们已经能够通过使用旧的FedAuth cookie和以下插件来重现该错误:(注意!我们不确定这是否与PROD上发生的事情相同,但至少可以会在我们的Logging系统中给出相同的错误)这很好,但是我认为您应该添加有关我们如何修改FedAuth cookie的内容的步骤,以使该问题在本地得以解决.-您可以使用此方法: 通过从以前的一些会话中获取FedAuth cookie的值很简单(在同一台机器上!不是从另一台机器上,那是行不通的),然后将其粘贴到FedAuth cookie的Value中并刷新页面.-

• We‘ve been able to re-produce the bug by using an old FedAuth cookie and this plugin: ( attention! We‘re not sure if this is the same thing that‘s happening on PROD, but at least it gives the same error in our Logging system ) This is good, but I think you should add the steps on how we‘re able to modify the content of the FedAuth cookie, to bring this problem to life, locally.- You can use this: It‘s simple by taking the Value of the FedAuth cookie from some previous sessions ( on the same machine! not from another machine, that won‘t work ) And pasting it into the Value of the FedAuth cookie and refreshing the page.-

用于修改Cookie的插件在Chrome中称为编辑此Cookie": -如果我们将此Cookie的内容更改为上一个会话的值,然后刷新(Chrome中为CTRL + R),则会得到臭名昭著的TokenSecurityException ID4243,而RP则要求立即执行FederatedSignout,因为我们无法从中恢复这种情况.

Plugin used to modify the cookie, in Chrome is called „Edit This Cookie": - If we change the content of this cookie to a value from a previous session, and hit the refresh ( CTRL + R in Chrome ) we get the infamous TokenSecurityException ID4243 and the RP calls for a immidiate FederatedSignout because we're unable to recover from this situation.

退出....

我可能还应该提到,我们认真对待了Microsoft MSDN在IsReferenceMode上标记为重要"的文章,并将其也添加到了我们的

I should also probably mention that we took's Microsoft MSDN's article marked "Important" on IsReferenceMode seriously and added it also to our

SessionAuthenticationModule_SessionSecurityTokenCreated事件:

SessionAuthenticationModule_SessionSecurityTokenCreated event:

e.SessionToken.IsReferenceMode = true;

e.SessionToken.IsReferenceMode = true;

取自MSDN:

重要! 要在参考模式下运行,Microsoft建议在global.asax.cs文件中为WSFederationAuthenticationModule.SessionSecurityTokenCreated事件提供一个处理程序,并在SessionSecurityTokenCreatedEventArgs.SessionToken属性中传递的令牌上设置SessionSecurityToken.IsReferenceMode属性.这样可以确保会话令牌针对每个请求都以引用方式运行,而不是仅在会话身份验证模块上设置SessionAuthenticationModule.IsReferenceMode属性.

Important! To operate in reference mode, Microsoft recommends providing a handler for the WSFederationAuthenticationModule.SessionSecurityTokenCreated event in the global.asax.cs file and setting the SessionSecurityToken.IsReferenceMode property on the token passed in the SessionSecurityTokenCreatedEventArgs.SessionToken property. This will ensure that the session token operates in reference mode for every request and is favored over merely setting the SessionAuthenticationModule.IsReferenceMode property on the Session Authentication Module.

下面是我们收到的整个SessionAuthenticationModule_SessionSecurityToken, 请检查我在其中发表的评论...它说明了所有功能:

Below is our whole SessionAuthenticationModule_SessionSecurityTokenReceived, please examine the comments I put into it ... it explains what everything does:

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!
            }
    }

推荐答案

这篇文章对我有帮助,因此可以帮助您和其他有此类错误的人.

this post helped me, so it can help you and others those have this kind of error.

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

来自链接.

希望它有用!

这篇关于消息:ID4243:无法创建SecurityToken.在令牌缓存中未找到令牌,并且在上下文中未找到Cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆