リッチクライアントとロールベースセキュリティ

何度となく書いているが、拙作のフレームワークはWindowsFormsベースのリッチクライアント(スマートクライアント)が主なターゲットである。このフレームワークにセキュリティの機能、具体的には認証の機能を組み込むことを予定しているのだが、不勉強な私は当初.NETにはコードベースセキュリティがメインで、Java等でお馴染のプリンシパル(ユーザやパスワード等の主体)を使用した、ロールベースの認証/承認フレームワークは無いのだと思っていた。
そんなわけは無く、調べてみると当然.NET Frameworkにもロールベースセキュリティのメカニズムは提供されており、その方法は大きく分けて3種類ある。

  • 強制セキュリティチェック

コードセキュリティと同様にPermissionオブジェクトを利用してチェックを行う方法。解説書にもよく掲載されており、見慣れた方法かもしれない。


PrincipalPermission permission =
new PrincipalPermission("Kazzz", "Administrator");
permission.Demand();
/* 以下、Administrator権限を必要とするコード */

  • 宣言セキュリティチェック

カスタム属性[PrincipalPermissionAttribute]を使用した、宣言的なセキュリティのチェック方法。私自身、.NETでカスタム属性が使えると判った時に、最も最初に考えたカスタム属性の使い道が、正にこの方法だった記憶がある。


[PrincipalPermission(SecurityAction.Demand, Name = "Kazzz", Role = "Administrator")]

以上はいずれも、セキュリティチェックが実行された時点でプリンシパルが存在していない、又はロールが適合していない場合に例外SecurityExceptionをスローする。明解だが、セキュリティチェックが失敗することも正常系の一部と考え、例外がスローされるのが好ましくない場合もある。また、できれば例外がスローされる前に、認証/承認の検査をしたいと思うのが開発者の人情だろう。そのような目的のために、いわばカスタム・セキュリティチェックのために提供されている方法もちゃんとある。

  • プリンシパルオブジェクトへの直接アクセス

認証が成功した時点で.NETのスレッドに関連付けられているはずの、IPrincipalインタフェースと、それに関連付けられたIIdentityインタフェースを実装したオブジェクトに直接アクセスして承認を行う方法。必ずしもPermissionオブジェクトは生成されないし、チェックが失敗しても例外はスローされない。ようは、全ては開発者側に任されている方法である。
例えばプリンシパルである、ユーザの主体(ID)を確認するのであれば、


IPrincipal principal = Thread.CurrentPrincipal;
if (principal.Identity.IsAuthenticated && principal.Identity.Name == "Kazzz")
{
/*認証済み且つID名が"Kazzz"のプリンシパルを必要とするコード */
}

また、主体に関連付けられたロールを検査するのであれば


IPrincipal principal = Thread.CurrentPrincipal;
if (principal != null && principal.IsInRole("Administrator") )
{
/* "Administrator"権限を必要とするコード */
}

と、きわめてシンプルにセキュリティチェックを実行できる。この点Javaに比べても非常に判りやすい。
また、IPrincipalインタフェースとそれに関連付けるIIdentityインタフェースの実装も非常に簡単であり、尚且つよく使いそうな実装(WindowsPrincipalやGenericPrincipal)も用意されており、使いやすい。

一番好みなのは、カスタム属性[PrincipalPermissionAttribute]を使用する方法なのだが、例外がスローされるのが気に食わないので、どこから呼ばれるのかを含めて実装を調査した上で、使えそうならばカスタム属性。駄目そうであれば、独自で用意したPrincipalとIdentityオブジェクトとDIxAOPコンテナの機能を用いて、セキュリティチェックを実装しようと考えている。
実はセキュリティチェックという処理は、AOPという技術が使えると判った当初、一番に実現してみたかった分野である。何故ならば、セキュリティチェックは、何時何処で発生するか判らない、処理の組み込み/取り外しを自由に行いたい、という要件が大抵は存在するからである。