2008年3月20日木曜日

ASP.NET MVCでアクセス制限をかける

Webアプリケーションには必ず必要だよね、認証(Authentication)と承認(Authorization)。 はてさてMVC形式でフォルダが割り振られ、物理フォルダの階層とルーティング機能でアクセスするURLのマッピングが一致してないASP.NET MVCではどのようにアクセス制限をかけましょうか。悩ましいですたい。

とりあえずスコットさんとこで確認したところMembershipやらRoleやらは今まで通り使えるってことなので、その辺aspnet_regsqlコマンドとか使って事前に準備を済ませ、ユーザー登録部分も普通にCreateUserWizardコントロールで作成、ログインはLoginコントロールを使って作成。 ただし、この場合runat="server"属性のformが必要になるので、美しさは少し欠ける。綺麗にするならHtml.Formヘルパー使って form要素を作成し、Viewもちゃんと自分でHTML書いてやるのがいいですよね。でも、その方法だと試しに作るには面倒すぎるので、とりあえずでよければ既存コントロールを使って自身にPostbackした後、Response.RedirectでContoroller/Action形式なりの URLに飛ばすことで認証はOKでしょう。

で、今度は承認。 まずはオーソドックスにViewsフォルダの中のController別フォルダにweb.configを入れてみた。 が、しかし上手くいかず。Authorizeするタイミングがこのタイミングだと遅いんだろうか。 ※本家Scottさんとこのコメント欄でそれらしいこと書いてた(ルーティングはOnPostMapRequestRequestHandler eventの後ですよって)。 で、ってことで、ルートのWeb.Configにlocation入れてみた。そしたら、これはすんなりできた。ロールに合わせてコントローラを分けるように作ればフォルダ単位で制御できるから今までとおなじように扱える。ただし、pathにアクションまで含めても上手くいかなかった。そんな使い方するのかどうか微妙だけど、気になるから調べてみたら、2つの方法で解決できる模様(実質1つか)。 まずは標準の方法でPrincipalPermission属性をアクション(コントローラのメソッド)に指定する方法。 ASP.NET MVC framework - Security もうひとつがSystem.Web.Mvc.ActionFilterAttributeを派生させてカスタム属性を作ってそこで制御する方法(要するにどっちも属性なんだけど)。 Rob Conery » ASP.NET MVC: Securing Your Controller Actions どっちも例外発生するからApplication_Errorで例外をハンドリング。 アクション毎に制限をかけたいっていう需要がどの程度これから出てくるか(個人的にそういう設計にするかどうか)分からないけど、ソースをいじるより web.configいじったほうが気分が楽だから、コントローラ単位の承認(Authorize)がいいんじゃなかろうかと思う次第でやんす。 全然話はかわるんですが↓これがちょっとすごい。 Chris van de Steeg’s blog - What’s practical is logical ASP.NET MVC+jQuery。テンプレートまで用意してる。ViewでJSON返すよ~とか、Ajaxで簡単取得(Htmlヘルパーも拡張してる)とか。