wif – 消息:ID4243:无法创建SecurityToken.在令牌缓存中找不到令牌,并且在上下文中未找到cookie

我们在生产环境中得到与此线程完全相同的错误.
[ WIF Security Token Caching

有人解决了这个错误吗?
消息:ID4243:无法创建SecurityToken.在令牌缓存中找不到令牌,并且在上下文中未找到cookie.

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

•我们在.NET Framework 4.5.1中使用内置Windows Identity Framework

•问题几乎总是与从RelyingParty#X更改为RelyingParty #Y相关联(例如,当用户点击RP#Y他没有要求退出时) – 当他在此事件后再次登录时,他’在RP#Y里面,他正好走到他要求的页面

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

•通过使用IsReferenceMode = true,我们的FedAuth cookie存储一个指向实际令牌的“指针”,该指针存储在我们的数据库

•我们使用自己的DatabaseSecurityTokenCache,它覆盖了SessionSecurityTokenCache中的函数.通过使用DatabaseSecurityTokenCache和IsSessionMode = true,我们对服务器场友好(但我们也保证在所有登录会话中都在同一服务器内)所以如果由于某种原因应用程序池死了,我们’能够通过DatabaseSecurityTokenCache从数据库获取令牌.我已经通过在会话中间完全杀死IIS来验证这一点(使用“net stop WAS”并使用“net start W3SVC”重新启动它,我们仍然可以从DatabaseSecurityTokenCache获取令牌).我也试过通过简单地使用开箱即用的SessionSecurityTokenCache来做同样的事情,并且会分别失败(如预期的那样)

认令牌生存期为20分钟(但如果用户可以将其更改为40或60分钟) – 这只会在用户下次登录时生效(并且90%的用户只使用认令牌20)分钟寿命)

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

•因此所有服务器都可以解密从其他服务器加密的cookie.

•我们在RelyingParty4和RelyingParty5(两个不同的依赖方)中有一个倒计时的javascript,用作“超时脚本”,以防用户无人看管他的计算机……当令牌即将退出时,他将退出到期 – (减去)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.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader,SecurityTokenResolver tokenResolver)中的Microsoft.IdentityModel,位于Microsoft.IdentityModel.Web.SessionAuthenticationModule的Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte []标记,SecurityTokenResolver tokenResolver). ReadSessionTokenFromCookie(Byte [] sessionCookie)位于System.Web.HttpApplication.SyncEventExecutionStep.System上的Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(Object sender,EventArgs eventArgs)的Microsoft.IdentityModel.Web.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken). System.Web.HttpApplication.ExecuteStep中的Web.HttpApplication.IExecutionStep.Execute()(IExecutionStep step,Boolean& completedSynchronously)

•我们已经能够通过使用旧的FedAuth cookie和这个插件重新生成错误:(注意!我们不确定这是否与PROD上发生的情况相同,但至少它给出了同样的结果我们的记录系统中的错误)这很好,但我认为您应该添加有关我们如何修改FedAuth cookie内容的步骤,以便在本地实现此问题.-您可以使用:
从以前的一些会话中获取FedAuth cookie的值很简单(在同一台机器上!而不是从另一台机器上,这将无法工作)并将其粘贴到FedAuth cookie的值中并刷新页面.-

用于修改cookie的插件,在Chrome中称为“编辑此Cookie”:
– 如果我们将此cookie的内容更改为上一个会话的值,然后点击刷新(Chrome中的CTRL R),我们就会得到臭名昭着的TokenSecurityException ID4243,并且RP会调用一个联合的FederatedSignout,因为我们无法从此恢复情况.

退出….

我还应该提一下,我们认真对待IsReferenceMode上的Microsoft MSDN文章标记为“重要”,并将其添加到我们的

SessionAuthenticationModule_SessionSecurityTokenCreated事件:

e.SessionToken.IsReferenceMode = true;

取自MSDN:

重要!
要在参考模式下运行,Microsoft建议为global.asax.cs文件中的WSFederationAuthenticationModule.SessionSecurityTokenCreated事件提供处理程序,并在SessionSecurityTokenCreatedEventArgs.SessionToken属性中传递的令牌上设置SessionSecurityToken.IsReferenceMode属性.这将确保会话令牌在每个请求的参考模式下运行,并且优于仅在会话认证模块上设置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!
            }
    }

解决方法

这篇文章帮助了我,所以它可以帮助你和其他有这种错误的人.
void Application_OnError()
{
  var ex = Context.Error;
  if (ex is SecurityTokenException){
     Context.ClearError();
     if (FederatedAuthentication.SessionAuthenticationModule != null){
         FederatedAuthentication.SessionAuthenticationModule.SignOut();
     }
   Response.Redirect("~/");
  }
}

this链接.

希望它有用!

相关文章

vue阻止冒泡事件 阻止点击事件的执行 &lt;div @click=&a...
尝试过使用网友说的API接口获取 找到的都是失效了 暂时就使用...
后台我拿的数据是这样的格式: [ {id:1 , parentId: 0, name:...
JAVA下载文件防重复点击,防止多次下载请求,Cookie方式快速简...
Mip是什么意思以及作用有哪些