ASP.NETの認証機構のうち、Windows認証と呼ばれる方式を用いて管理者のみがアクセス可能なページを持つWebアプリを実装してみる。
前回では、ASP.NETにおける認証と認定について基本的な解説を終えたので、今回は実際的な解説に移ることにする。まずはWindows認証について解説していこう。
すでに解説したとおり、Windows認証を利用する場合、認証と認定の多くをIISやWindowsに任せられるので、コードで表現すべき処理はそれほど多くはない。特定のユーザーやロールに応じてアクセスを許可する、しない、という程度のアクセス制御であれば、主な仕事は「web.config」ファイルでの設定やACL(Access Control List:アクセス制御リスト)の構成ということになる。
最初のサンプルとして示すASP.NETアプリケーション「winauth」は、以下のようなものだ。認証されたユーザーならばだれでもアクセスできるdefault.aspx(図18.1)と、adminグループに所属するユーザーだけがアクセスできるadmin.aspx(図18.2)から構成される。
default.aspxは、図18.1に示すように、認証されたユーザー(PageクラスのUserプロパティ)と、ワーカープロセスの実行ユーザー(WindowsIdentity.GetCurrentメソッドで取得)の情報、それにadmin.aspxを開くためのボタンが表示されるというもの。このボタンは、認証されたユーザーがadminグループに所属しているときだけ有効となる。また画面には現れないが、このページにアクセスしたユーザーの名前をファイル「access.log」に記録する作業も行われる。
もう1つのadmin.aspxでは目を引くような作業は何も行われないが、ACLを編集して、adminグループに属していないユーザーからのアクセスを拒否するようにしておく。
それでは、まずはIISマネージャを使って、アプリケーションを格納するディレクトリの準備から始めることにする。ここでは「c:\winauth」を仮想ディレクトリ「winauth」としてアクセスできるように設定する。
次に仮想ディレクトリwinauthのプロパティ・ダイアログボックスで、匿名アクセスを拒否するように認証方式を変更する。IISで利用できる認証方式には、統合Windows認証、基本認証、ダイジェスト認証などがあるが、いずれの認証方式を選択してもWindows認証に影響はないので、ネットワーク環境に応じて選択すればよい。
ASP.NETのWindows認証が多くの場合イントラネットで利用されることを考えれば、通常は統合Windows認証を利用するのがいいだろう。この認証方式では、ローカルマシンへのログインに使用したアカウントとパスワードがそのままIISへのログインに用いられるので、アカウントが統一的に管理されているネットワークならば、いちいちアカウント名とパスワードを入力することなくアプリケーションへとアクセスできるようになる。それに、パスワードが安全に送信されるというメリットもある。
ただし、統合Windows認証はIEでしかサポートされていないうえ、プロキシ・サーバを通過できない場合も少なくないので、常に利用できるとは限らない。そうした場合は基本認証を利用すればよい。この場合は、アプリケーションへのアクセス時に必ずログイン・ダイアログボックスが表示される。また、パスワードがクリア・テキストに近い状態で送信されてしまう。場合によってはSSLを利用するなど、何らかの対策を講じる必要があるかもしれない。なお、ダイジェスト認証は安全にパスワードを送信できるが、ドメイン・ネットワークが構成されていないと利用できない。
以上の設定を終えたら、ディレクトリ「c:\winauth」にweb.config(リスト18.1)とdefault.aspx(リスト18.2)、それにadmin.aspx(リスト18.3)を作成する。
web.config、default.aspx、admin.aspxのダウンロード(winauth.zip)
<configuration>
<system.web>
<authentication mode="Windows" />
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Security" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.IO" %>
<html>
<head>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
if (User.IsInRole("kskserver\\admin")) {
admin.Enabled = true;
}
aspuser.DataSource = CreateDataSource(User.Identity);
workuser.DataSource
= CreateDataSource(WindowsIdentity.GetCurrent());
DataBind();
try {
string filename = Server.MapPath(".") + @"\access.log";
StreamWriter writer
= new StreamWriter(new FileStream(
filename, FileMode.Append, FileAccess.Write));
writer.WriteLine(User.Identity.Name);
writer.Close();
}
catch (Exception ex) {
Message.Text = ex.Message;
}
}
}
ICollection CreateDataSource(IIdentity identity) {
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add(
new DataColumn("property name", typeof(string)));
dt.Columns.Add(new DataColumn("value", typeof(string)));
Type t = identity.GetType();
PropertyInfo[] properties = t.GetProperties();
foreach (PropertyInfo pi in properties) {
dr = dt.NewRow();
dr[0] = pi.Name;
dr[1] = pi.GetValue(identity, null);
dt.Rows.Add(dr);
}
DataView dv = new DataView(dt);
return dv;
}
void admin_Click(object sender, EventArgs e) {
Response.Redirect("admin.aspx");
}
</script>
</head>
<body>
<form runat="server">
<p>Windows認証に認証されたユーザー</p>
<asp:DataGrid id="aspuser" runat="server" />
<hr>
<p>ワーカープロセスのアクセス・トークン</p>
<asp:DataGrid id="workuser" runat="server" />
<hr>
<asp:Button id="admin" Text="管理ページ" Enabled="false"
OnClick="admin_Click" runat="server" />
</form>
<asp:Label id="Message" runat="server" />
</body>
</html>
<%@ Page Language="C#" %>
<html>
<head>
<script runat="server">
</script>
</head>
<body>
<h1>管理用ページ</h1>
<p>このページはadminグループのメンバのみがアクセスできます</p>
</body>
</html>
Copyright© Digital Advantage Corp. All Rights Reserved.