"Буфер времени истечения" SessionSecurityTokenHandler для WIF 4.5 в веб-роли Azure
Каждый.
Что означает "Буфер времени истечения"? Позвольте мне объяснить это вам.
В моем проекте облачного сервиса Azure есть только одна веб-роль. И я интегрировал пространство имен ACS с некоторым поставщиком удостоверений. И провайдер идентификации выдаст токен. В любом случае, будет экземпляр SessionSecurityToken. И моя веб-роль справится с ее истечением.
Вот пример кода,
void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
{
Trace.TraceInformation("SessionAuthentication_SessionSecurityTokenReceived event");
SessionSecurityToken sessionToken = e.SessionToken;
if (sessionToken.ValidTo < DateTime.UtcNow)
{
Trace.TraceInformation("SessionSecurityToken with token expiration time {0} expired at {1}. Its key expiration time is {2}",
sessionToken.ValidTo,
DateTime.UtcNow,
sessionToken.KeyExpirationTime);
Response.Write("{\"message\":\"token timeout\"}");
}
}
Однако не каждый раз, когда sessionToken.ValidTo меньше DateTime.UtcNow будет вызывать исключение истечения срока действия токена.
Message string SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:12:37. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event
Message string SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:14:37. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event
Message string SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:16:37. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event
Message string SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:35:32. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event
И только последняя проверка времени вызовет исключение, как это.
Message string <TraceSource>System.IdentityModel</TraceSource>
<Object><TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"><TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier><Description>Throwing an exception.</Description><AppDomain>/LM/W3SVC/1273337584/ROOT-1-130155861607927929</AppDomain><Exception><ExceptionType>System.IdentityModel.Tokens.SecurityTokenExpiredException, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>ID4255: The SecurityToken is rejected because the validation time is out of range.
ValidTo: '6/13/2013 9:12:31 AM'
ValidFrom: '6/13/2013 9:02:32 AM'
Current time: '6/13/2013 9:35:32 AM'</Message><StackTrace> at System.IdentityModel.Tokens.SessionSecurityTokenHandler.ValidateSession(SessionSecurityToken securityToken)
at System.IdentityModel.Tokens.SessionSecurityTokenHandler.ValidateToken(SecurityToken token)
at System.IdentityModel.Services.SessionAuthenticationModule.ValidateSessionToken(SessionSecurityToken sessionSecurityToken)
at System.IdentityModel.Services.SessionAuthenticationModule.SetPrincipalFromSessionToken(SessionSecurityToken sessionSecurityToken)
at System.IdentityModel.Services.SessionAuthenticationModule.AuthenticateSessionSecurityToken(SessionSecurityToken sessionToken, Boolean writeCookie)
at System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs)
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp;amp; completedSynchronously)
at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
</StackTrace><ExceptionString>System.IdentityModel.Tokens.SecurityTokenExpiredException: ID4255: The SecurityToken is rejected because the validation time is out of range.
ValidTo: '6/13/2013 9:12:31 AM'
ValidFrom: '6/13/2013 9:02:32 AM'
Current time: '6/13/2013 9:35:32 AM'</ExceptionString></Exception></TraceRecord></Object>
Так может кто-нибудь объяснить это поведение? В чем проблема? Как этого избежать?
Благодарю.
Артур
1 ответ
Вы можете переопределить поведение SessionAuthenticationModule по умолчанию, установив собственный тайм-аут. На самом деле я столкнулся с проблемой необходимости реализовать это, чтобы обойти 2-минутное окно тайм-аута токена SAML, выдаваемого провайдером идентификации (не-Azure), к которому я подключался.
Вы можете сделать это путем создания подкласса SessionAuthenticationModule или обработки события SessionSecurityTokenReceived в Global.asax.
Вот пример, заимствованный из книги Виторио Берточчи "Программирование Windows Identity Foundation", в которой истекает срок действия 2-минутного скользящего окна. Хотя вам придется изменить пространства имен на "System.IdentityModel", поскольку они изменились, когда Windows Identity Foundation был добавлен в.NET Framework 4.5.
<%@ Application Language=”C#” %>
<%@ Import Namespace=”Microsoft.IdentityModel.Web” %>
<%@ Import Namespace=”Microsoft.IdentityModel.Tokens” %>
<script runat=”server”>
void SessionAuthenticationModule_SessionSecurityTokenReceived
(object sender, SessionSecurityTokenReceivedEventArgs e)
{
DateTime now = DateTime.UtcNow;
DateTime validFrom = e.SessionToken.ValidFrom;
DateTime validTo = e.SessionToken.ValidTo;
double halfSpan = (validTo – validFrom).TotalMinutes / 2;
if ( validFrom.AddMinutes( halfSpan ) < now && now < validTo )
{
SessionAuthenticationModule sam = sender as SessionAuthenticationModule;
e.SessionToken = sam.CreateSessionSecurityToken(
e.SessionToken.ClaimsPrincipal,
e.SessionToken.Context,
now, now.AddMinutes(2), e.SessionToken.IsPersistent);
e.ReissueCookie = true;
}
}
//...