特集:クライアントステート管理、3つの手法Visual Studio Magazine(8/9 ページ)

» 2004年12月28日 10時30分 公開
[Matthew Gibbs, Rob Howard,FTPOnline]

クッキーをクライアント状態の管理に利用する

 最後に、クライアント状態を管理するテクニックとして、クッキーを考察していこう。

 多くのWeb開発者は知らないだろうが、クッキーは良い標準規格ではない。しかしながら、すべての代表的なブラウザはクッキーをサポートし、Webアプリケーションの開発テクノロジーもまたクッキーを利用している。

 ASP.NETは、2つの処理のためにクッキーを利用している。それは、「セッション状態」と「フォーム認証」だ。

 セッション状態に関連するクッキーは、「.ASPXSession」となる。このクッキーは、セッションデータにリクエストを結びつけるために利用するSessionIDを格納する。一方、フォーム認証に関連するクッキーは、「.ASPXAUTH」だ。このクッキーは、暗号化された資格情報を格納する。資格情報は解読され、ユーザーが再認証されるときに用いられる。

 Internet Explorerで[ツール]メニューの[インターネットオプション]を選択し、[インターネットオプション]ダイアログボックスを表示すると、システムに保存されているすべてのクッキーを確認できる。[全般]タブで[設定]ボタンをクリックし、[設定]ダイアログボックスを表示してほしい。そして[ファイルの表示]ボタンをクリックすると、エクスプローラで「Temporary Internet Files」フォルダがポップアップする。

 その後、「種類」でソートして「テキスト文章」となっているものや、「名前」でソートして「Cookie」という名前のものがクッキーの実体だ。

 クライアントがクッキーを利用することを保証できれば、クッキーは状態を管理する良い方法だと言えよう。クッキーには、文字列型(あるいは文字列に変換可能な型)であれば、「名前/値」の組み合わせで、値を保存できる。クッキーにおけるただひとつの制限は、格納できるデータの量だ。ほとんどのブラウザは、最大で4Kバイトのクッキー容量しか保存サポートしない。

 ASP.NETにおけるクッキーの動きは単純だ。

 たとえば、ユーザーがどのロールに属しているのかという情報を格納する場面で、クッキーを利用できる。リクエストのたびにユーザーのロールをデータベースから参照するのではなく、特定の「UserRolesクッキー」が存在しない場合にのみ、ユーザーのロールを参照する。そして、UserRolesクッキーを作成してユーザーが属するロールを加える。

 後続するリクエストにおいては、単純にUserRolesクッキーを開き、ロールを抽出して、それをカレントユーザーが属するロールとして加えればよい(リスト1)。

リスト1■クッキーを利用した開発はとても容易(C#)
//************************************************
//
// Application_AuthenticateRequestイベント
//
// クライアントがアプリケーションで認証されるとき、
// ユーザーがどのセキュリティロールに属するかを決定し、
// 組み込みの「User」の代わりに、カスタムなIPrincipal
// セキュリティオブジェクトで置き換え、アプリケーション
// において、「Users.IsInRole」を使ってロールのチェックを
// できるようにする。
//
// ロールは、暗号化されたクッキーによって
// ブラウザのメモリにキャッシュされる。
// もしこのセッションにおいてクッキーがまだ存在しないなら、
// クッキーを作成する
//
//************************************************
void Application_AuthenticateRequest(
Object sender, EventArgs e) {
String[] roles = null;

if (Request.IsAuthenticated == true) {
// このセッションでまだクッキーが存在しないなら、
// ロールのクッキーを作成する
if ((Request.Cookies["userroles"] == null) ||
(Request.Cookies["userroles"].Value
== "")) {
// UserRolesテーブルからロールを取り出し、
// それをクッキーに加える
roles = UserRoles.GetUserRoles(
User.Identity.Name);
CreateRolesCookie(roles);
} else {
// クッキーからロールを取得する
FormsAuthenticationTicket ticket =
FormsAuthentication.Decrypt(
Context.Request.Cookies["userroles"].Value);

// ログインしているユーザーと
// クッキーで提示されるユーザーが同一かを確かめる
if (ticket.Name !=
Context.User.Identity.Name) {
// UserRolesテーブルからロールを取り出し、
// それをクッキーに加える
roles = UserRoles.GetUserRoles(
User.Identity.Name);

CreateRolesCookie(roles);
} else {
// ロールのデータを
// 文字列の配列に変換する
ArrayList userRoles =
new ArrayList();

foreach (String role in
ticket.UserData.Split(
new char[] {';'} )) {
userRoles.Add(role);
}

roles = (String[])
userRoles.ToArray(typeof(String));

}
}

// 認証チケット内のロールを含む
// カスタムなプリンシパルをリクエストに追加する
Context.User = new
GenericPrincipal(Context.User.Identity,
roles);
}
}

//************************************************
//
// CreateRolesCookie
//
// カレントユーザーのためのロールを保存する
// クッキーを作成するのに使われる
//
//************************************************
private void CreateRolesCookie(string[] roles) {

// ロールの文字列を作成する
String roleStr = "";
foreach (String role in roles) {
roleStr += role;
roleStr += ";";
}

// 認証チケットとなるクッキーを作成する
FormsAuthenticationTicket ticket = new
FormsAuthenticationTicket(
1, // バージョン
Context.User.Identity.Name, // ユーザー名
DateTime.Now, // 発行時刻
DateTime.Now.AddHours(1), // 1時間で期限切れにする
false, // 永続的に保存されないクッキー
roleStr // ロール
);

// チケットを暗号化する
String cookieStr =
FormsAuthentication.Encrypt(ticket);

// クッキーをクライアントに送信する
Response.Cookies["userroles"].Value =
cookieStr;
Response.Cookies["userroles"].Path = "/";
Response.Cookies["userroles"].Expires =
DateTime.Now.AddMinutes(5);
}

 Webサイトにおいて、ユーザーが属するロールを格納するためにクッキーを利用できる。リクエストのたびにユーザーのロールをデータベースから引っ張ってくるのではなく、特定の「UserRolesクッキー」が存在しない場合のみに、ユーザーのロールを引っ張ってくる。そしてUserRolesクッキーを作成して、ユーザーが属するロールを加える。その後、単純にUserRolesクッキーを開き、ロールを抽出して、それをカレントユーザーが属するロールとして加えればよい。

© Copyright 2001-2005 Fawcette Technical Publications

注目のテーマ