wp/自動リンク切れチェック
10.3.1 | フォーム認証入門
http://msdn.microsoft.com/ja-jp/library/dd297831.aspx
それでは、フォーム認証がどのくらい使いやすいのかをみてみましょう。リスト10-2に示すアプリケーションコードを調べ、判断してください。アプリケーションのユーザーインターフェイスは、PublicPage?.aspxとProtectedPage?.aspxの2つで構成されています。前者は一般ユーザーに公開されますが、後者は認証済みユーザーにのみ公開されます。ここでの「認証済みユーザー」とは、第3のページであるLoginPage?.aspx経由でログインしてきたユーザーを意味します。このページは、ユーザー名とパスワードの入力を要求します。有効なユーザー名とパスワードは、Web.configに格納されています。
ソースコードの詳細解説を始める前に、アプリケーションをテストドライブに設定しておきましょう。次のような操作を行ってください。
PublicPage?.aspx、LoginPage?.aspx、および(アプリケーションルートにある)Web.configを、wwwrootか任意の仮想ディレクトリにコピーします。
仮想ルート内にSecretという名称のサブディレクトリを作成し、ProtectedPage?. aspxと(Secretサブディレクトリにある)Web.configをSecretサブディレクトリにコピーします。
ブラウザを起動し、PublicPage?.aspxを開きます。wwwrootにコピーしている場合には、http://localhost/publicpage.aspxと入力します。
[View Secret Message]ボタンをクリックします。
[View Secret Message]ボタンは、内部でResponse.Redirectを呼び出してSecret\ProtectedPage?.aspxを呼び出します。しかし、ProtectedPage?.aspxは、認証済みユーザーにのみ公開されているため、ASP.NETはLoginPage?.aspxのログインフォームを表示します(図10-6参照)。
ユーザー名フィールドにJeff、パスワードフィールドにimbatmanと入力します。
ProtectedPage?.aspxが表示されます。この時点までくれば、既に認証を受けているため、以降の要求でクッキーとして使用される認証チケットが発行されていることになります。
PublicPage?.aspxに移動します。
[View Secret Message]ボタンを再度クリックします。
ProtectedPage?.aspxが再度表示されますが、今度は、ユーザー名とパスワードの入力を要求されません。理由は簡単です。要求とともに送信された認証クッキーは、ASP.NETのフォーム認証モジュール(すべての要求をリッスンします)に対して、Jeffという認証済みユーザーであることを通知しているからです。図10-7に示す専用の挨拶画面が表示されます。
ブラウザをいったん終了させて再起動し、PublicPage?.aspxを呼び出します。
[View Secret Message]ボタンを再度クリックします。今度はログインを要求されます。これは、認証チケットを含んでいるクッキーが、セッションクッキーであるためです。つまり、ブラウザを閉じると、その内容も消滅してしまうのです。
▲図10-6 フォーム認証ログインフォーム
▲図10-7 秘密のメッセージ
未認証ユーザーはProtectedPage?.aspxを開けず、それを呼び出すとログインフォームに移動されていますが、この背景はいったいどうなっているのでしょうか?この秘密はWeb.configにあります。より正確に言えば、このアプリケーション用に用意されている2つのWeb.configファイルの内容にあります。アプリケーションルートにあるWeb.configは、フォーム認証を有効にし、ログインページを明示します。
コピー
authentication mode="Forms">
<forms loginUrl="LoginPage.aspx">
...
</forms>
/authentication>
さらに、このファイルは、有効なユーザー名とパスワードのリストを保持するcredentialsセクションを含んでいます。
コピー
credentials passwordFormat="Clear">
<user name="Jeff" password="imbatman" />
<user name="John" password="redrover" />
<user name="Bob" password="mxyzptlk" />
<user name="Alice" password="nomalice" />
<user name="Mary" password="contrary" />
/credentials>
SecretサブディレクトリのWeb.configファイルも、同じようにセキュリティ確保面で重要な役割を持っています。このファイルには、次のようなコードが記述されています。
コピー
authorization>
<deny users="?" />
/authorization>
このコードはURL許可を担当しています。つまり、ASP.NETのURL許可モジュール(System.Web.Security.UrlAuthorizationModule?)に対して、ホストディレクトリの任意のASP.NETファイルへ、未認証ユーザーからのアクセスを拒否するように指示しているのです。「?」は、未認証ユーザーの別名である匿名ユーザーを示します。このディレクトリ内のファイルをだれかが要求してくると、ASP.NETはその要求内に有効なクッキーがアタッチされているかどうかを調べます。クッキーが存在する場合、ASP.NETはそれを復号し、改ざんされていないことを検証した後、要求に割り当てている識別情報を取り出します。暗号化と検証は無効にすることができますが、デフォルトでは有効になっています。クッキーが存在しない場合、ASP.NETはその要求をログインページに切り替えます。
ユーザー名とパスワードの入力要求とその有効性チェックなどの実際の認証は、LoginPage?.aspxで行われます。次に示すコードは、ユーザーが入力したユーザー名とパスワードを、Authenticateという名称の静的なSystem.Web.Security.Forms Authenticationメソッドに渡しています。このメソッドは、ユーザー名とパスワードが有効である(つまり、Web.configのcredentialsセクションにリストされてます)場合にはtrueを返し、無効である場合にはfalseを返します。
コピー
if (FormsAuthentication?.Authenticate (UserName?.Text, Password.Text))
Authenticateメソッドがtrueを返してきた場合、次のメソッドは認証クッキーを作成し、それを送出する応答にアタッチし、ユーザーを目的のページに切り替えます。
コピー
FormsAuthentication?.RedirectFromLoginPage? (UserName?.Text, false);
RedirectFromLoginPage?に渡す第2のパラメータは、認証がセッションクッキー(false)か永続化クッキー(true)かのいずれであるかを指定します。フォーム認証を採用する多くのサイトは、チェックボックスをユーザーに提示し、送信するクッキーの種類を選択する権利をユーザーに与えています。このため、[Keep me logged in on this site]などのラベルのチェックボックスが表示された場合、そのチェックボックスを有効にすると、有効期間がブラウザセッションと独立している認証クッキーが発行されると考えてよいでしょう。
ProtectedPage?.aspxは、Secretサブディレクトリ唯一のASPXファイルです。その他のファイルが存在する場合、それらのファイルもログインフォームにより保護されます。保護というのは、ディレクトリ単位で適応されるものなのです。2つの異なる保護レベルを2つのファイルセットに適応したい場合、それらのファイルセットは個別のディレクトリに格納する必要があります。それぞれのディレクトリに置かれるWeb.configファイルは、ディレクトリ内のファイルの保護方式を規定します。
▼リスト10-2 単純なフォーム認証
コピー
PublicPage.aspx
html>
<body>
<h1>Public Page</h1>
<hr>
<form runat="server">
<asp:Button Text="View Secret Message" OnClick="OnViewSecret"
RunAt="server" />
</form>
</body>
/html>
script language="C#" runat="server">
void OnViewSecret (Object sender, EventArgs e)
{
Response.Redirect ("Secret/ProtectedPage.aspx");
}
/script>
コピー
ProtectedPage.aspx
%@ Page Language="C#" %>
html>
<body>
<h1>Protected Page</h1>
<hr><br>
<% Response.Write (Context.User.Identity.Name + ": "); %>
Be careful investing your money in dot-coms.
</body>
/html>
コピー
LoginPage.aspx
html>
<body>
<h1>Please Log In</h1>
<hr>
<form runat="server">
<table cellpadding="8">
<tr>
<td>
User Name:
</td>
<td>
<asp:TextBox ID="UserName" RunAt="server" />
</td>
</tr>
<tr>
<td>
Password:
</td>
<td>
<asp:TextBox ID="Password" TextMode="password"
RunAt="server" />
</td>
</tr>
<tr>
<td>
<asp:Button Text="Log In" OnClick="OnLogIn"
RunAt="server" />
</td>
<td>
</td>
</tr>
</table>
</form>
<hr>
<h3><asp:Label ID="Output" RunAt="server" /></h3>
</body>
/html>
script language="C#" runat="server">
void OnLogIn (Object sender, EventArgs e)
{
if (FormsAuthentication.Authenticate (UserName.Text,
Password.Text))
FormsAuthentication.RedirectFromLoginPage (UserName.Text,
false);
else
Output.Text = "Invalid login";
}
/script>
コピー
Web.config (Application Root)
configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="LoginPage.aspx">
<credentials passwordFormat="Clear">
<user name="Jeff" password="imbatman" />
<user name="John" password="redrover" />
<user name="Bob" password="mxyzptlk" />
<user name="Alice" password="nomalice" />
<user name="Mary" password="contrary" />
</credentials>
</forms>
</authentication>
</system.web>
/configuration>
コピー
Web.config (Secret Subdirectory)
configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
/configuration>