Я создал приложение с 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 на стороне сервера от сбоя авторизации из-за того, что сессия завершилась.
AFAIK: не существует типизированного исключения или свойства, которое может определить это. Единственный способ, которым я смог определить это - что кажется мне хаком - это просмотреть строку сообщения ошибки и найти что-то вроде "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>
Проблема в том, что у меня нет строки в сообщении об ошибке, которая указывает на "Отказано" или "Доступ запрещен" - и я не знаю, почему это решение работает на локальном хосте IIS или хосте VS2010, но не на удаленном сервере IIS7. Может быть, я упускаю какой-то непонятный параметр конфигурации? Есть ли лучший способ сделать это в целом?