このアプリケーションでは、役割ベースのフォーム認証を実装しました。これはRoleModuleを使用して処理されており、RoleデータをCookieに保存し、Cookieからデータを読み取ってオブジェクトをインスタンス化するたびに行われIPrincipal
ます。このコードは次のApplication_OnPostAcquireRequestState
メソッドで実行されます。
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
RolesCookieを現在のプリンシパルオブジェクトデータで更新します。
このページには、Cookieを読み取り、Cookieを更新し、有効期限が切れた場合にチケットを更新するFormsAuthentication_OnAuthenticate
方法があります。Global.asax
また、このメソッドでは、チケットの有効期限が切れた場合に、セッションオブジェクトにユーザー名の値を設定しようとします。
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.User
として設定されNULL
ます。これで、ユーザーがページを要求すると、ログインページにリダイレクトされます。ただし、Cookieはまだ存在します。この場合も、ユーザーがページをリクエストしようとすると、context.User.IsAuthenticated
プロパティがに設定されtrue
、ユーザーはそれぞれのページに移動します。また、FormsAuthentication_OnAuthenticate
メソッドでは、セッション値を設定しようとすると、セッションオブジェクトがであるためエラーがスローされますNULL
。
ここで達成したいのは、永続的なCookieの場合、認証チケットがタイムアウトした後、ユーザーはログアウトしない、つまりユーザーを再認証する必要があるということです。
どうすればこれを達成できますか?私が間違っていなければ、設定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と同じものを確認しました。