我使用Silverlight4、RIA Services创建了一个应用程序,并使用ASP.NET Membership进行认证/授权。
我的web.config文件中有以下内容:
<system.web>
<sessionState timeout="20"/>
<authentication mode="Forms">
<forms name="_ASPXAUTH" timeout="20"/>
</authentication>
我看过了许多关于如何处理客户端认证/会话超时的不同策略。即:如果客户端在x分钟(这里是20)内处于空闲状态,然后他们通过UI执行某些操作触发RIA/WCF调用,我希望能够捕获该事件并适当地处理它(例如将他们带回登录界面) - 简而言之:我需要一种区分真正的服务器端DomainException与授权失败因为会话超时的方法。
据我所知:没有类型化的异常或属性可以确定这一点。我能够确定这一点的唯一方法 - 似乎是一个hack:检查错误的消息字符串并查找类似“Access denied”或“denied”的内容。例如,像这样的内容:
if (ex.Message.Contains("denied"))
// this is probably an auth failure b/c of a session timeout
所以,这是我目前正在做的事情。如果我使用VS2010内置服务器进行运行和调试,或者在本地主机IIS中运行,则可以正常工作。如果我将超时设置为1分钟,登录后等待超过一分钟并触发另一个调用,则会在异常处断点,并进入上述if代码块,一切正常。
然后,我将应用程序部署到远程IIS7服务器,并尝试进行相同的测试,但它不起作用。因此,我添加了日志跟踪,并在发生异常的事件中找到以下内容:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>131076</EventID>
<Type>3</Type>
<SubType Name="Error">0</SubType>
<Level>2</Level>
<TimeCreated SystemTime="2011-10-30T22:13:54.6425781Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{20c26991-372f-430f-913b-1b72a261863d}" />
<Execution ProcessName="w3wp" ProcessID="4316" ThreadID="24" />
<Channel />
<Computer>TESTPROD-HOST</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.TraceHandledException.aspx</TraceIdentifier>
<Description>Handling an exception.</Description>
<AppDomain>/LM/W3SVC/1/ROOT/sla-2-129644844652558594</AppDomain>
<Exception>
<ExceptionType>System.ServiceModel.FaultException`1[[System.ServiceModel.DomainServices.Hosting.DomainServiceFault, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message></Message>
<StackTrace>
at System.ServiceModel.DomainServices.Hosting.QueryOperationBehavior`1.QueryOperationInvoker.InvokeCore(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.DomainServices.Hosting.DomainOperationInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
</StackTrace>
<ExceptionString>System.ServiceModel.FaultException`1[System.ServiceModel.DomainServices.Hosting.DomainServiceFault]: (Fault Detail is equal to System.ServiceModel.DomainServices.Hosting.DomainServiceFault).</ExceptionString>
</Exception>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
问题在于错误信息中没有指示“denied”或“Access denied”的字符串,我不确定为什么这种解决方法适用于本地IIS或VS2010主机,但不适用于远程IIS7服务器。我是否缺少某些不明确的配置设置?总的来说,有更好的方式来处理这个问题吗?