8

Silverlight4、RIA Servicesでアプリケーションを構築しましたが、認証/承認にASP.NET Membershipを使用しています。Silverlight RIA Services - クライアント認証セッションのタイムアウトを最適に処理する方法

私のweb.configファイルには、このあります

<system.web> 
<sessionState timeout="20"/> 
<authentication mode="Forms"> 
    <forms name="_ASPXAUTH" timeout="20"/> 
</authentication> 

を私はクライアント側で認証/セッションタイムアウトに対処する方法についての異なる戦略の数を読みました。つまり、クライアントがx分(ここでは20)アイドル状態で、RIA/WCF呼び出しをトリガーするUIで何か操作を行うと、そのイベントをトラップして適切に対処したいと思います。ログイン画面) - 一言で言えば、セッションがタイムアウトしたため、真正なサーバー側のDomainExceptionと認証エラーとを区別する方法が必要です。

AFAIK:これを特定できる型付き例外またはプロパティはありません。私がこれを判断できる唯一の方法は、ハックのように見えます。エラーのメッセージ文字列を調べ、「アクセス拒否」や「拒否」のようなものを探します。たとえば、次のようにこのような何か:

if (ex.Message.Contains("denied")) 
    // this is probably an auth failure b/c of a session timeout 

だから、これは私が現在やっているし、私が実行した場合、それが動作し、デバッグはVS2010から内蔵のサーバとのいずれか、または私はlocalhostをIISで実行する場合。タイムアウトを1分に設定してログインし、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[]&amp; outputs) 
     at System.ServiceModel.DomainServices.Hosting.DomainOperationInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp; outputs) 
     at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc) 
     at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc) 
     at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; 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> 

問題は、私は「拒否」または「アクセス拒否」を示すエラーメッセージの文字列を持っていないということです - と私はなぜこのソリューションがlocalhost IISまたはVS2010ホストで動作し、リモートIIS7サーバでは動作しないのかは不明です。私がここで不足しているいくつかの不明確な設定がありますか?これを行う一般的な方法がありますか?

答えて

10

あなたはおそらくこれまでにこれを得ていますが、this articleはDomainOperationExceptionの使用とエラーコードのチェックについて説明しています。便利なアクセスのために

dex.ErrorCode == ErrorCodes.NotAuthenticated || dex.ErrorCode == ErrorCodes.Unauthorized 

(ブログへとケースで我々緩いアクセス)ここジョシュEastburnにより、ブログの記事があります:

で作業している開発者から頻繁に来る質問SilverlightおよびWCF RIAサービス:Silverlightアプリケーションが一定期間アイドル状態になったときに例外がスローされるのはなぜですか?予想通り、認証されたセッションのタイムアウトが原因です。しかしそれはそれほど単純ではありません。 Silverlightはクライアント/サーバーアーキテクチャを使用するため、クライアントは無期限にサーバーとは独立して動作することができます。これは、Silverlightクライアントがサーバー側のタイムアウトが実現されたサーバーへの呼び出しを行うときのみです。クライアントとサーバーのタイムアウトの問題を処理するオプションがいくつかあります(さらにいくつか考えてみることもできます)。セッションのタイムアウトを取り除くというセキュリティの問題に関心がない場合は、タイムアウトを長くするかweb.configで設定したり、サーバー上でシンプルなメソッドを呼び出して「Keep Alive」として機能するDispatcherTimerをSilverlightクライアントに作成します。サーバー側のタイムアウトと同期しているDispatcherTimerをSilverlightクライアントに追加し、有効期限が切れる前にセッションをアクティブに保ち続けるように警告またはプロンプトを出します。ただし、これは、新しいサーバー要求が行われたときにタイマーを同期させるために余分な努力を必要とします。サーバーが通常どおりタイムアウトを処理し、Silverlightクライアントでタイムアウトを正常に処理できるようにします。つまり、タイムアウトはサーバーコールアクティビティによって決まり、アクティビティはSilverlightクライアントを制限しません(つまり、コンテキスト内のクライアントサイドデータにアクセスする)。これらの3つのオプションのうち、私はセキュリティと使いやすさのバランスが最も良いと同時に、アプリケーションに不必要な複雑さを加えないことがわかりました。世界的にこれらのサーバー側のタイムアウトを処理するためには、あなたが持っていれば構築App.xaml.csまたはグローバルのViewModel負荷のApplication_UnhandledExceptionの方法のいずれかで次のロジックを追加することができます。

// Check for Server-Side Session Timeout Exception 
var dex = e.ExceptionObject as DomainOperationException; 
if ((dex != null) && (dex.ErrorCode == ErrorCodes.NotAuthenticated || dex.ErrorCode == ErrorCodes.Unauthorized) && WebContext.Current.User.IsAuthenticated) 
{ 
    // A server-side timeout has occurred. Call LoadUser which will automatically 
    // authenticate if "Remember Me" was checked, or prompt for the user to log on again 
    WebContext.Current.Authentication.LoadUser(Application_UserLoaded, null); 
    e.Handled = true; 
} 

以下の定数がのerrorCodeクラス内に定義される:

public static class ErrorCodes 
{ 
    public const int NotAuthenticated = 0xA01; 
    public const int Unauthorized = 401; 
} 

場合、サーバ側セッションタイムアウト、任意subsequ ent呼び出しはDomainOperationExceptionを返します。返されたErrorCodeを調べることで、それが認証エラーであるかどうかを判断し、それに応じて処理することができます。私の例では、WebContext.Current.Authentication.LoadUser()を呼び出して、できるだけユーザーを再認証しようとしています。ユーザーが自動的に再認証できない場合でも、Application_UserLoadedメソッドをコールバックします。 WebContext.Current.User.IsAuthenticatedをチェックして、前の操作を続行するか、ホームページにリダイレクトしてログイン用に再設定する必要があるかどうかを判断できます。ここでは、ユーザーが認証されていない場合、ログインダイアログが表示さAppliation_UserLoadedコールバックでいくつかのコードの例です:

// Determine if the user is authenticated 
if (!WebContext.Current.User.IsAuthenticated) 
{ 
    // Show login dialog automatically 
    LoginRegistrationWindow loginWindow = new LoginRegistrationWindow(); 
    loginWindow.Show(); 
} 

あなたのコードをテストするには、にweb.configファイルであなたのタイムアウト値を設定することができますタイムアウトそう 小さな値がすぐに発生します。あなたが作業溶液中で、このコードのすべてを見ることが

<authentication mode="Forms"> 
    <forms name=".Falafel_ASPXAUTH" timeout="1" /> 
</authentication> 

を希望する場合は、CH私たちのSilverlight RIA Template on CodePlexを出してください。

+0

ありがとう - これは私が探していたものです。私はそのブログに記載されているオプション3に向かっていましたが、それを正しく得る時間はまだありませんでした。これは私にとってはうまくいくはずです。 – zenocon

関連する問題