解説インサイド .NET Framework第14回 ロールベース・セキュリティ インフォテリア株式会社 |
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ユーザーを表す。
|
|
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ファイルを開くと、中には次のようなエントリがある。
|
|
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に次のような記述があるとする。
|
|
web.configファイルによるアクセス制御 |
このアクセス制御はUrlAuthorizationModuleによって行われるので、HttpContextクラスのUserプロパティの内容が重要になる。web.configにこれを記述しなくても、test.aspxが次のように記述されていれば、同じ結果になる。
|
|
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にも設定していることに注意してほしい。
|
|
独自のロールを定義する場合のglobal.asaxの記述例 | |
ASP.NETでは、ユーザーのアクセスが認証を必要とするときに、AuthenticateRequestイベントが発生する。フォーム認証を利用する場合、このタイミングで独自のロールを定義することができる。 |
こうしておけば、あとはweb.configで次のように記述して「ロールベース」セキュリティを実現できる。
|
|
独自ロールを利用したアクセス制御を行うためのweb.configファイル記述例 |
INDEX | ||
解説 インサイド .NET Framework | ||
第14回 ロールベース・セキュリティ | ||
1.アイデンティティとプリンシパル | ||
2.ロールベース・セキュリティの適用 | ||
3.Webアプリケーションとロールベース・セキュリティ | ||
4.WebアプリケーションとNTFSアクセス制御 | ||
「解説:インサイド .NET Framework 」 |
- 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|