連載プログラミングASP.NET第19回 フォーム認証を実装したASP.NETアプリケーション 田口 景介2003/07/26 |
![]() |
|
Page1
Page2
|
|
フォーム認証その2
以上のように、FormsAuthenticationクラスに用意されたヘルパ・メソッドを利用すれば簡単にフォーム認証を利用できるが、ロールベースの認定が利用できないなど柔軟性に欠けるところがある。また、web.configに資格情報を登録しなければならず、セキュリティ上問題になる場合もある。そこで、これらのデメリットを解消したフォーム認証のサンプルであるアプリケーション「formauth2」を次に作成する。
このformauth2アプリケーションでは、FormsAuthenticationクラスのヘルパ・メソッドに頼らず、資格情報を独自のXMLファイルに登録し、これを用いて認証を行う。また、formauthアプリケーションでは利用できなかったロールベースの認定も可能にする。
■カスタム認証
formauth2アプリケーションは、次の6つのファイルから構成されている。default.aspxとadmin.aspxは先のformauthと同じものなので、ここでは残る4つのファイルについて解説する。
- web.config
- login.aspx(ログイン・フォーム)
- default.aspx(formauthアプリケーションと同じ)
- admin.aspx(formauthアプリケーションと同じ)
- global.asax(Application_AuthenticateRequestイベント・ハンドラ)
- users.xml(資格情報を登録したxmlファイル)
formauth2アプリケーションのダウンロード(formauth2.zip)
formauth2アプリケーションのweb.configは、formauthアプリケーションのそれとほとんど同じだが、FormsAuthenticationクラスを利用しないので、次のリスト19.3に示すようにcredentials要素やuser要素は取り除かれている。
|
|
| リスト19.3 formauth2アプリケーションのweb.config |
代わりに資格情報は、リスト19.4に示すようなXMLファイル(users.xml)に登録される。このXMLの構造は特に定められたものではなく、筆者が扱いやすいように適当に定義したものだ。各ユーザーに1つのUserInfo要素が対応し、その子要素としてユーザー名とパスワード、それにユーザーが所属するロールを示す、name要素、password要素、role要素が含まれるようになっている。role要素に指定したロールによって認定が行えるところが、FormsAuthenticationクラスを使った認証との大きな違いである。
|
|
| リスト19.4 資格情報を記述したusers.xml |
以上のusers.xmlを読み込み、認証を行っているのがFormsAuthentication.Authenticateメソッドの代替版として定義しているlogin.aspxのAuthenticateメソッドである。このメソッドに関連するコードをlogin.aspxより抜粋して次のリスト19.5に示す。
|
|
| リスト19.5 users.xmlにより認証を行うAuthenticateメソッド(login.aspxの一部) |
ここで行われている処理はごく単純なもので、XmlSerializerクラスを利用してusers.xmlを読み込み、メソッドのパラメータに指定されたユーザー名(username)とパスワード(password)に一致するエントリが存在するかを確認しているだけである。非常に簡単な処理だが、これだけでも認証は可能だ。もっとも、より実際的には、このサンプルのようにパスワードを平文のまま保存せずに、暗号化処理を追加する必要があるし、できればXMLファイルよりもデータベースを利用すべきだろう。
ところで、XmlSerializerとは、XMLファイルの構造に対応するクラスを宣言し(ここではルート要素に対応するAuthInfoクラスとUserInfoクラス)、Deserializeメソッドを呼び出すだけで、XMLファイルの構造を保ったまま適切なオブジェクトに読み込んでくれる大変便利な仕組みである。いずれ川俣氏の「連載:.NETで簡単XML」で丁寧に解説されると思われるので、ここでは詳しい解説は割愛する。
■フォーム認証におけるロールベースの認定
Windows認証を利用したときは、特別な処理を行わなくても、web.configのauthorization要素を使ったり、Page.UserプロパティからIsInRoleメソッドを呼び出したりして、ロールベースの認定を行うことができた。これは、ユーザーが認証されると、そのユーザーが所属しているグループがそのままロールとして参照される仕組みが提供されていたからだ。一方フォーム認証では、認証プロセスがアプリケーションに任されているため、このような便利な仕組みは用意されていない。ロールベースの認定を利用したければ、それなりの処理を実装しなければならないのである。
フォーム認証でロールベースの認定を利用するには、Page.Userプロパティ(またはContext.User)に格納されているIPrincipalオブジェクトを適切にセットアップしなければならない。前回Windows認証のwinformアプリケーションで利用したように、IPrincipal.IsInRoleメソッドを呼び出したり、authorization要素でロールベースの認定を行ったりすると、このIPrincipalオブジェクトが参照されるのである。従って、このオブジェクトの作成時に、ユーザーとロールの関係を指定してやれば、フォーム認証でもWindows認証と同じようにロールベースの認定が利用できるようになる。
それでは、どこでIPrincipalオブジェクトのセットアップを行えばよいのだろうか。IsInRoleメソッドを利用するだけならば、その手前でオブジェクトを作成すればよいのだが、web.configのauthorization要素を利用するとなるとそうはいかない。authorization要素による認定は、ページのコードが実行される前に、暗黙的に行われるからだ。そこでこの処理はアプリケーション・レベルのイベント・ハンドラとして実装する必要がある。具体的には、ファイルglobal.asaxにApplication_AuthenticateRequestの名前でメソッドを宣言し、ここに処理を記述すればよい。このメソッドはHttpApplicationクラスのAuthenticateRequestイベントのハンドラとして機能し、ASP.NETのセキュリティ・モジュールによってユーザーが認証されると呼び出されるようになる。なお、このメソッドはFormsAuthentication_OnAuthenticateの名前で宣言することもできる。こちらはFormsAuthenticationクラスのAuthenticateイベントのハンドラとして機能するもので、フォーム認証専用に用いられるものである。
ここでIPrincipalオブジェクトを作成すればよいのだが、そのためには認証されたユーザーが所属するロールを調べる手段が必要になる。その方法はいろいろと考えられるが、ここでは認証チケットにその情報を格納することにする。認証チケットは認証時に作成され、以後セッションが終了するまでクッキーとして保存されている。このため必要なときにはいつでも参照でき、この種の用途には適している。
■ロールベースによる認定処理の実装
さて、それでは実装について解説していこう。まずはロール情報を含めたカスタム認証チケットを作成する過程から見ていくことにする。formauthアプリケーションでは、FormsAuthentication.RedirectFromLoginPageメソッドを利用していたので、認証チケットは自動的に作成されていたが、今回はロール情報を含めるために同等の処理を自前で実装しなければならない。その処理を行っているのが、login.aspxで宣言されているRedirectFromLoginPageメソッドである(リスト19.6)。
|
|
| リスト19.6 カスタム認証チケットを作成するRedirectFromLoginPageメソッド(login.aspxの一部) |
ここでは認証チケットの実体であるFormsAuthenticationTicketオブジェクトを作成し、これをクッキーとして登録する処理を行っている。なお、FormsAuthenticationクラスのメソッドを利用するときは、web.configのforms要素に指定されたパラメータが参照されて認証チケットが作成されるが、ここではFormsAuthenticationクラスにてアクセス用のメソッドが用意されている値(クッキー名とリダイレクトURL)だけは参照し、それ以外の値(チケットの有効期限(timeout)と保護(protection))には固定値を指定している。
さて、このRedirectFromLoginPageメソッドの第2パラメータにロールを文字列として渡せば、ユーザー定義データを格納するために用意されているUserDataプロパティを利用して、認証チケットにロール情報が含まれるようになる。そこに指定されるロール情報は、前節で解説したAuthenticateメソッドによってusers.xmlから読み出されたもので、[ログイン]ボタンのClickイベント・ハンドラで以下のように受け渡される。
void login_Click(object sender, EventArgs e) {
UserInfo userinfo;
// 認証に成功すると、認証されたユーザーの情報がuserinfoに格納される
if ((userinfo = Authenticate(tbUsername.Text, tbPassword.Text))
!= null) {
RedirectFromLoginPage(
userinfo.name, userinfo.role, persist.Checked);
} else {
Message.Text = "失敗しました。パスワードを確認してください";
}
}
こうして認証チケットに格納されたロール情報は、リスト19.7に示すApplication_AuthenticateRequestメソッドで参照され、IPrincipalオブジェクトの作成に利用される。フォーム認証の場合、IPrincipalオブジェクトの実体はGeneralPrincipalクラスのオブジェクトとして作成され、これはFormsIdentityオブジェクト(資格情報を格納する)とロール情報から構成される。1つの資格情報には複数のロール情報を対応付けできるため、ロール情報は文字列の配列(string[])として指定できる。ただ、formauth2アプリケーションでは処理を単純にするため、ロール情報を単一のstringオブジェクトとして扱っている。
|
|
| リスト19.7 IPrincipalオブジェクトの作成を行うglobal.asax |
こうしてContext.Userにロール情報を含む資格情報がセットアップされると、ロールベースの認定が利用できるようになる。例えば、次に示すようにlocation要素以下に認定の設定を行えば、admin.aspxにはロールadminに所属するユーザーだけがアクセスできるようになる。
|
|
| リスト19.8 formauth2アプリケーションのweb.config |
■
さて、長らくご愛読いただいた本連載だが、今回でひとまず最終回とさせていただく。ASP.NETのフレームワークは感心するほど巨大で、解説すべき事項は尽きることはなさそうだが、基本的な機能についてはおおむね網羅できたと思う。より実践的なプログラミング講座でお会いできることを期待しつつ、最後までお付き合いいただいた読者の方々に感謝したい。![]()
| INDEX | ||
| プログラミングASP.NET | ||
| 第19回 フォーム認証を実装したASP.NETアプリケーション | ||
| 1.フォーム認証を実装したサンプル・アプリケーション | ||
| 2.カスタム認証とロールベースの認定を用いたフォーム認証 | ||
| 「連載 :プログラミングASP.NET」 |
TechTargetジャパン
- 新人プログラマーのためのInsider.NETの歩き方 2012 (2012/5/22)
晴れて.NETプログラマーとなる新人が効率的に開発技術を習得するには? 大量にある記事群の中から新人が読むべきお勧めを厳選して紹介 - jQuery MobileでJavaScriptプログラミング (2012/5/17)
jQuery Mobileは手軽なだけでなく、JavaScriptのAPIも充実しており、独自機能の実装もできる。今回は「グローバル設定」と「イベント」を解説 - Windows上で開発するための開発環境構築入門 (2012/5/16)
Windowsを使ってチームで開発している? なのにサーバOSを設定・運用した経験がない? そうなら、今すぐ学ぼう - 「コントラクト」でアプリのサンドボックスを乗り越える! (2012/5/11)
Metroスタイル・アプリはサンドボックスの中で動作する。それを乗り越えてほかのアプリと連携する仕組み「コントラクト」を解説
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -


