解説

インサイド .NET Framework [改訂版]

第10回 ロールベース・セキュリティ

吉松 史彰
2003/09/10
Page1 Page2 Page3 Page4

Webアプリケーションとロールベース・セキュリティ

 Windows上で動作するWindowsアプリケーションや、コマンド・プロンプトで動作するコンソール・アプリケーションの場合、ロールベース・セキュリティにおいて利用するのはWindowsのユーザーであることが多いだろう。その場合は、先述した例のようにAppDomainクラスのSetPrincipalPolicyメソッドを実行するだけで、.NET Frameworkが自動的にWindowsPrincipalオブジェクトを作成してくれる。だがWebアプリケーションの場合は、必ずしも認証方式がWindowsであるとは限らない。事実、ASP.NETには3種類の認証方式(Forms、Windows、Passport)が用意されている。これらの方式で認証された場合、ロールベース・セキュリティはどうなるのだろうか。

 ASP.NETでは、3種類の認証方式のどれかを使って認証が行われた場合、それぞれに対応するプリンシパル・オブジェクトが作成される。例えばASP.NETのweb.config構成ファイルに次の記述を行うと、Windows認証が行われ、認証にパスすればWindowsPrincipalクラスのインスタンスが作成される。そのオブジェクトのIdentityプロパティに設定されているのは、WindowsIdentityクラスのインスタンスになる。このオブジェクトはIISが認証したWindowsユーザーを表す。

<authentication mode="Windows"/>
<authorization>
  <deny users="?"/>
</authorization>
ASP.NETでWindows認証を行うためのweb.config構成ファイルの設定

 フォーム認証を利用するために<authentication>要素のmode属性をFormsに設定して、ログイン・ページの作成などの適切な作業を行い、正しくログインした場合は、GenericPrincipalクラスのインスタンスが作成される。そのオブジェクトのIdentityプロパティに設定されているのは、FormsIdentityクラスのインスタンスになる。このオブジェクトは、フォーム認証のコードで認証されたユーザーを表す。

 これらのオブジェクトを作成するのは、それぞれの認証方式に対応するHTTPモジュールに格納されているクラスの役割だ。%SYSTEMROOT%\Microsoft.NET\Framework\vx.x.x\CONFIGフォルダ(通常はC:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\CONFIG)に格納されているmachine.configファイルを開くと、中には次のようなエントリがある。

<httpModules>
  <add name="OutputCache"
       type="System.Web.Caching.OutputCacheModule" />
  <add name="Session"
       type="System.Web.SessionState.SessionStateModule" />
  <add name="WindowsAuthentication"
       type="System.Web.Security.WindowsAuthenticationModule" />
  <add name="FormsAuthentication"
       type="System.Web.Security.FormsAuthenticationModule" />
  <add name="PassportAuthentication"
       type="System.Web.Security.PassportAuthenticationModule" />
  <add name="UrlAuthorization"
       type="System.Web.Security.UrlAuthorizationModule" />
  <add name="FileAuthorization"
       type="System.Web.Security.FileAuthorizationModule" />
</httpModules>
machine.configに記述されている認証のためのモジュール(抜粋)

 つまり、Windows認証が行われるときはSystem.Web.Security.WindowsAuthenticationModuleクラスがそれを担当し、フォーム認証が行われるときはSystem.Web.Security.FormsAuthenticationModuleが担当する。これらのクラスがプリンシパル・オブジェクトを作成する。

 作成されたプリンシパル・オブジェクトは、Webアプリケーションでは2つの場所に格納される。1つはSystem.Web.HttpContextクラスのUserプロパティだ。もう1カ所は、前述のSystem.Threading.Thread.CurrentPrincipalプロパティだ。前者に対する設定は、WindowsAuthenticationModuleやFormsAuthenticationModuleが行い、後者の設定はSystem.Web.Security.DefaultAuthenticationModuleクラスが行っている。この2カ所から参照されているオブジェクトは同一だ。つまり、次のコードはtrueを返す。

  bool IsTheSame = System.Object.ReferenceEquals(
                      Context.User, Thread.CurrentPrincipal);

 なぜ同じオブジェクトを2カ所から参照しているかというと、それは用途が違うからだ。ASP.NETの承認機能、つまりweb.configファイルの<authorization>要素の記述(System.Web.Security.UrlAuthorizationModuleが処理する)と、ファイルのNTFSアクセス権(System.Web.Security.FileAuthorizationModuleが処理する)によるアクセス制御のときに使われるのは、HttpContextクラスのUserプロパティである。一方、すでに説明したPrincipalPermissionクラスでのチェックに使われるのが、ThreadクラスのCurrentPrincipalプロパティである。例えばweb.configに次のような記述があるとする。

<location path="test.aspx">
  <system.web>
    <authorization>
      <allow users="User1" />
      <deny users="*" />
    </authorization>
  </system.web>
</location>
web.configファイルによるアクセス制御

 このアクセス制御はUrlAuthorizationModuleによって行われるので、HttpContextクラスのUserプロパティの内容が重要になる。web.configにこれを記述しなくても、test.aspxが次のように記述されていれば、同じ結果になる。

<%@Page Language="C#"%>
<%@Import Namespace="System.Security.Permissions"%>
<%
  PrincipalPermission perm
    = new PrincipalPermission("User1", null);
  perm.Demand();
%>
PrincipalPermissionクラスによるアクセス制御

 どちらも、User1という名前のユーザー以外はtest.aspxにアクセスできなくなる。もっとも、web.configに記述した場合はログイン・ページが表示されるのだが、aspxファイルに記述した方はセキュリティ例外になるので、ユーザーに対する見た目を考慮しなければならない。

独自のロール定義

 ASP.NETでWindows認証を行っているときは、ロールはすなわちWindowsのグループなのだが、フォーム認証を行っているときは、ロールはどうなるのだろうか。実は、デフォルトではロールは作成されない。誰をどのロールに属させるかは、開発者が書くコードに一任されている。あるロールにどのアイデンティティが属しているかを決定する仕組みは、それぞれの認証モジュール(XXXAuthenticationModule)クラスのIsInRoleメソッドの実装内容に依存する。

 例えば、WindowsPrincipalクラスのIsInRoleメソッドでは、恐らくWindowsのSAM(Security Account Manager)データベースにアクセスして、Identityプロパティで表されているWindowsユーザーが指定されたWindowsグループに属しているかどうかを調べているだろう。何らかのデータベースでユーザーとロールとの関連を管理しているシステムであれば、GenericPrincipalクラスを作成するときにデータベースにアクセスして、ユーザーが属するグループをすべて取得し、文字列の配列にしてGenericPrincipalクラスのコンストラクタに渡せばよい。あとはIsInRoleメソッドが、その配列に入っている文字列に対してはtrue、入っていなければfalseを返す。例えば次のようなコードで、ManagersとSalesの2つのロールに属するUserを定義できる。

  HttpContext.Current.User = new GenericPrincipal(
          principal.Identity, new string[]{"Managers", "Sales"});

 次の疑問は、このコードはどこに記述すればいいのか、どこで実行すればいいのかということだろう。ASP.NETでは、HttpApplicationクラスにAuthenticateRequestイベントがある。ユーザーのアクセスが認証を必要とする場合、このイベントが発生する。そこで、global.asaxファイルに次の記述を行えばよいことになる。Thread.CurrentPrincipalにも設定していることに注意してほしい。

<%@Application Language="C#" %>
<%@Import Namespace="System.Security.Principal"%>
<%@Import Namespace="System.Threading"%>
<script runat="server">
protected void
    Application_AuthenticateRequest(object o, EventArgs e) {
  IPrincipal principal = HttpContext.Current.User;
  if ((principal != null) && (principal.Identity.Name == "User1")) {
    HttpContext.Current.User = new GenericPrincipal(
        principal.Identity, new string[]{"Managers", "Sales"});
    Thread.CurrentPrincipal = HttpContext.Current.User;
  }
}
</script>
独自のロールを定義する場合のglobal.asaxの記述例
ASP.NETでは、ユーザーのアクセスが認証を必要とするときに、AuthenticateRequestイベントが発生する。フォーム認証を利用する場合、このタイミングで独自のロールを定義することができる。

 こうしておけば、あとはweb.configで次のように記述して「ロールベース」セキュリティを実現できる。

<location path="test.aspx">
  <system.web>
    <authorization>
      <allow roles="Managers" />
      <deny users="*" />
    </authorization>
  </system.web>
</location>
独自ロールを利用したアクセス制御を行うためのweb.configファイル記述例
 

 INDEX
  解説 インサイド .NET Framework [改訂版]
  第10回 ロールベース・セキュリティ
    1.アイデンティティとプリンシパル
    2.ロールベース・セキュリティの適用
  3.Webアプリケーションとロールベース・セキュリティ
    4.WebアプリケーションとNTFSアクセス制御
 
インデックス・ページヘ  「解説:インサイド .NET Framework [改訂版]」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間