QA@IT

.NET MVC5でページごとの承認の作り方

5088 PV

ASP.NETで、以下の仕様でページごとの承認処理を実装しているアプリケーションがあります。

・ページごとにページIDをもつ
・子ページのPage_Loadイベントで、マスタページのプロパティにページIDを設定する
・マスタページのPage_Loadイベントで、セッションに格納されているユーザIDと、設定されたページIDを使い、ページにアクセスする権限を確認する
・アクセスする権限がなければ、メニューに飛ばす
ユーザIDと、アクセスできるページのIDはデータベースに格納しています。

.NET MVC5で一部の画面を作りなおそうとしていますが、どうすれば同様の処理を実装できるかよくわからず、困っています。
以下の二通りの可能性を軸にできるのか調べたいと思っているのですが、できそうでしょうか。
他にいい方法があるのでしょうか。

・案1
Global.aspxの適切なメソッドに承認処理を実装する。
認証されてない場合はログイン画面に飛ばす。
承認処理では、要求されているページのIDを取得する。
ユーザIDはセッションかどこか、Global.aspxからアクセスできる場所にいれておく。
承認に失敗した場合、メニューに飛ばす。

・案2
ASP.NETと同じような処理の実装を模索する。
マスターレイアウトに子ページからIDを設定する。
マスターレイアウトは読み込み前に承認処理が実装されているメソッドを呼び出す。

よろしくお願いします。

  • 認証・承認に全くの独自実装をされている理由が何だか分かりませんが、これを機会に ASP.NET が標準でサポートしているメンバーシップ・ロールプロバイダによる認証・承認に切り替えることは考えないのでしょうか? -
  • ユーザIDとロールとの対応と、ロールとアクセス可能なページのIDの対応をデータベースにて管理しています。当時検討したとき、データベースで管理する場合のいいサンプルコードがみつからなかったように記憶しています。 -
  • サンプルコードが見つからなかった??? そんな事はないはずです。ASP.NET が標準でサポートしている認証・承認システムを熟知しているがそれが使えないから独自実装したのか、よく知らないまま使えるかどうか評価もしないで独自実装したのか、どっちですか? 後者だと思われるのですが。 -
  • 今ざっとググっても、自分でDBからとってきたデータをもとに判定しているコードはみつかりませんでした。ググり方が悪いのかもしれませんが、ググるのにかかる時間も含め、最短な方法をまずあたってみる予定です。案2は案1やデフォルトの機能を使うより汚いので、あまりとりたくはないですが。 -
  • 私の質問に対する答えは後者ということでしょうか? であれば、まず ASP.NET が標準でサポートしているメンバーシップ・ロールプロバイダによる認証・承認がどういうものか勉強されることをお勧めします。 -
  • 調べてみますね。 -
  • ↑「プログラミング ASP.NET 2.0」をみても、そこまでのは載ってないようにみえます。Web.configでのロールの記述といったいになってる気がする。 -
  • 私の一番最初のコメントの質問に対する質問者さんの答えは "No" ということですね。であれば、すみませんが自分はお役に立てそうもありません。他の方の回答をお待ちください。 -
  • 何かよさそうな案があれば、工数との兼ね合いを考えながら、広く検討する予定です。ただ、案件の規模からいって、フレームワークの作りこみは困難です。 -

回答

時間無くて全然試せていないのですが、思いついた範囲で

  • Controllerでやる

Controllerでは表示するページがわかっている(埋め込まなくてもページIDが判断できると思っています)でしょうし、セッションも取得できると思いますので、
Controllerで判断して問題あれば ControllerのRedirect メソッドでメニューに飛ばしてはどうでしょうか

  • GlobalFilterを作成

Global.aspxで作成したFilterを登録できます。
Filterとは ActionFilterAttributeクラスを継承したクラスになります。
アクションの実行前に判定するのであれば OnActionExecuting を使えばいいんじゃないかと思います。

global.aspx

GlobalFilters.Filters.Add(new MyFilter(), 1);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

MyFilter.cs

public class MyFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
         // context.RouteData などを使って処理。
         // 問題があれば  context.Result = new RedirectResult("~/Menu");
         // などとしてみる
    }
}
  • Global.aspx で実装

自前で認証する( web.config で authentication mode="None" と deny users="?" ) ようにして

    <authentication mode="None" />  
    <authorization>  
      <deny users="?" />  
    </authorization> 

Application_AuthenticateRequestApplication_EndRequest を実装する方法です。

ただし Application_AuthenticateRequest では Sessionは見れなかったと思うので、Cookieに入れておいてRequest.Cookiesで参照する必要があると思います。
ページはRequestからわかるかと思います。

protected void Application_AuthenticateRequest(object sender, EventArgs e){
    // ユーザーチェック
    if (Request.Cookies["CookieName"] != null){
        var identity = new GenericIdentity("user1");
        var pricinpal = new GenericPrincipal(identity, new string[] { });
        HttpContext.Current.User = pricinpal;
    }
}

protected void Application_EndRequest(object sender, EventArgs e){
    if (this.Response.StatusCode == 401){
        // 401 ならメニューへ
        Response.Redirect("http://localhost/AppName/Menu");
    }
}

他にも方法はあると思いますがメンテのしやすさも考えて選択されるといいとおもいます。

編集 履歴 (0)
  • ありがとうございました。GlobalFilterで要求されたサイトを判断しながら判断する形を検討しようと思います。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。