最後に、クライアント状態を管理するテクニックとして、クッキーを考察していこう。
多くの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