1

アプリケーションでは、ロールベースのフォーム認証を実装しています。これはRoleModuleを使用して処理されています。ロールデータはクッキーに保存されます( )。クッキーからデータを読み込み、IPrincipalオブジェクトをインスタンス化するたびに処理されています。このコードはApplication_OnPostAcquireRequestState方法で実行される:コンテキストの再初期化FormsAuthenticationTicketタイムアウト後のユーザ

HttpApplication application = source as HttpApplication; 
HttpContext context = application.Context; 

if (context.User.Identity.IsAuthenticated && 
     (!Roles.CookieRequireSSL || context.Request.IsSecureConnection)) 
{ 
//Read the roles data from the Roles cookie.. 

context.User = new CustomPrincipal(context.User.Identity, cookieValue); 
Thread.CurrentPrincipal = context.User; 
} 

これはcontext.Userオブジェクトを初期化します。サーバーに要求が行われるたびに、ユーザーは上記のフローを使用して認証されます。 Application_EndRequestでは、現在のプリンシパルオブジェクトデータでロールクッキーを更新します。

ページにはFormsAuthentication_OnAuthenticateメソッドがあります。このページでは、クッキーを読み取り、クッキーを更新し、有効期限が切れている場合は チケットを更新します。また、このメソッドでは、チケットが期限切れになった場合にセッションオブジェクトにユーザー名の値を設定しようとします。ここで

FormsAuthentication oldTicket = FormsAuthentication.Decrypt(context.Request.Cookies[FormsAuthentication.FormsCookieName].Value); 
if(oldTicket != null) 
{ 
    if(oldTicket.Expired) 
    { 
     try 
     { 
      HttpContext.Current.Session["UserName"] = userName; 
     } 
     catch 
     { 
      //Log error. 
     } 

    FormsAuthentication newTicket = new FormsAuthenticationTicket(oldTicket.Version, oldTicket.Name, DateTime.Now, 
      DateTime.Now.AddMinutes(30), oldTicket.IsPersistent, oldTicket.UserData); 

    string encryptedTicket = FormsAuthentication.Encrypt(newTicket); 
    HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); 
    if (isPersistent) 
    { 
     httpCookie.Expires = DateTime.Now.AddMinutes(300); 
    } 
} 

は、web.configファイルに設定私たちのフォームです:

<forms defaultUrl="Default.aspx" domain="" loginUrl="Login.aspx" name=".ASPXFORMSAUTH" timeout="20" slidingExpiration="true" /> 

セッションタイムアウトは20分です。

問題:。ユーザーは30以上分間アイドル状態であれば(FormsAuthチケットの更新時間です)、 でcontext.User.Identity.IsAuthenticated値は、役割モジュールはfalseあり、そしてcontext.UserNULLとして設定されています。ユーザーがページを要求すると、ログインページにリダイレクトされます。ただし、まだ のCookieが残っています。再びユーザーがページを要求しようとすると、context.User.IsAuthenticatedプロパティはtrueに設定され、ユーザーはそれぞれ ページに移動します。また、FormsAuthentication_OnAuthenticateメソッドでセッションの値を設定しようとすると、セッションオブジェクトがNULLであるため、エラーがスローされます。

私がここで達成したいのは、永続的なクッキーの場合、認証チケットがタイムアウトした後、ユーザーはログアウトしてはならないということです。すなわち、ユーザーは を再認証する必要があります。

どうすればこの問題を解決できますか? 私が間違っていない場合は、context.Userを設定して目的を解決する必要がありますが、どうすればいいですか?

追加情報:

チケットの有効期限が切れると、私はページを要求しようとした後、イベントビューアにエラーメッセージを示しています。私はに保存されている、標準のマシンキーの設定を使用しています

Event code: 4005 
Event message: Forms authentication failed for the request. Reason: The ticket supplied has expired. 
Event time: 08-02-2012 20:02:05 
Event time (UTC): 08-02-2012 14:32:05 
Event ID: 048e3238ade94fd6a7289bac36d130ef 
Event sequence: 76 
Event occurrence: 2 
Event detail code: 50202 

Process information: 
Process ID: 21692 
Process name: w3wp.exe 
Account name: IIS APPPOOL\ASP.NET v4.0 Classic 

をweb.configではなく、自動生成されたものです。また、すべてのエラーに対してプロセスIDとそのプロセスIDを確認しました。

答えて

1

私はついにこの問題を解決しました。 FormsAuthenticationチケットがタイムアウトすると、FormsAuthentication_OnAuthenticateはコンテキストを設定できませんでした。Userオブジェクトは、認証イベントのMSDN documentationに指定されている:あなたは FormsAuthentication_OnAuthenticateイベント中にユーザー・プロパティの値を指定しない場合は

、クッキーやURLに フォーム認証チケットによって提供されるアイデンティティがあります中古。

その理由は、ユーザのユーザ名をticket.Nameに設定していないためです。これは空の文字列です。したがって、AuthenticateイベントがユーザーのIDを取得してFormsIdentityインスタンスを作成できなかった可能性があります。解決策として、期限切れのチケットを更新するときに、GenericIdentityオブジェクトを作成してから、それを使用してcontext.Userに設定します。

IIdentity identity = new GenericIdentity(username, "Forms"); 
context.User = new CustomPrincipal(identity); 
関連する問題