by WebSurfer
2010年7月30日 08:37
あまり役に立たないかもしれませんが、ASP.NET 標準の Forms 認証システムで、認証チケットが期限切れになっているかどうかを判定するという話です。なお、前提条件としてクッキーが有効になっていることを想定しています。
例えば、一旦認証を受けたユーザーが、ログオフせず、ブラウザを立ち上げたまま、長時間席を外すなどして、タイムアウトに設定した時間を超えてアクセスしなかった場合を考えてください。
ユーザーが席に戻ってきて再度アクセスした場合、アクセスしたページに匿名アクセスを許可してなければ、ログインページにリダイレクトされるというのが Forms 認証の通常の設定です。
そこで、ユーザーに認証チケットが期限切れとなっていることを知らせるにはどうしたらいいでしょうか?
User.Identity.IsAuthenticated ではダメです。認証されているか否かは判定できますが、認証チケットが期限切れかどうかはわかりませんから。
一旦認証を受けたが、認証チケットが期限切れになっているというのは、サーバー側では以下の条件で判定できるはずです。
-
要求 HTTP ヘッダーに認証クッキーが含まれる。
-
認証クッキーの中の認証チケットが期限切れ。
認証クッキーと認証チケットは違うことに注意してください。クッキーはチケットの入れ物に過ぎません。認証チケットの有効期限は、認証クッキーの Value の中に入っている情報の一つです。HttpCookie.Expires ではありません。
一般的に、一旦認証クッキーの発行を受ければ、セッションが切れない限り(注)、次の要求の時にブラウザはサーバーにクッキーを送ります。(注:認証クッキーを「永続化」している場合は話が違ってきます。詳しくは別の記事「Froms 認証クッキーの永続化」を見てください)
認証クッキーを取得し、その Value を復号して認証チケットを取得し、ユーザー名、期限切れか否かなどの情報を取得できます。それで上記の 2 つの条件を確認できます。例えば、ログインページにリダイレクトされたときに期限切れを知らせる場合は、Global.asax で以下のようにします(もしくは HTTP Module を作る)。
void FormsAuthentication_Authenticate(object sender,
FormsAuthenticationEventArgs args)
{
// "/login.aspx" は実際に合わせて適宜変更してください。
if (Request.CurrentExecutionFilePath != "/login.aspx")
{
return;
}
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (null == authCookie)
{
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch (Exception ex)
{
return;
}
if (null == authTicket)
{
return;
}
if (authTicket.Expired)
{
// 知らせるための処置を書く。例えば下記:
Context.Response.Write("<h1><font color=red>" +
"Forms Authentication Ticket Expired" +
"</font></h1><hr>");
}
}
認証チケットが期限切れの場合、FormsAuthenticationModule が認証クッキーを削除しているようで、タイミングによっては認証クッキーは取得できないので注意してください。
従って、認証クッキーを取得できるのは、FormsAuthenticationModule.Authenticate イベント以前のタイミングになります。