10

私は、コントローラとアクションで承認属性を使用するASP.NET MVCアプリケーションを使用しています。これはうまくいっていますが、新しいしわが現れました。ASP.NET MVC:アクション内の承認 - 推奨パターンまたはこれは匂いですか?

オブジェクト:出荷

役割:送料、会計、一般ユーザ

発送ワークフローに移動します。状態Aでは、出荷時のみ編集可能です。状態Bでは、会計のみで編集することができます。

私はShipmentControllerとEdit Actionを持っています。私はAuthorization属性を入れて編集アクションをこれらの2つのロールだけに制限することができますが、これはShipmentがどの状態にあるかを区別しません。サービス呼び出しの前にアクションの中で何らかの承認を行う必要があります実際に編集アクションを実行する権限があります。良い方法は、アクション内部の許可を持っていただきました

1):

だから、私は2つの質問が残っています。コントローラアクションがサービスを呼び出すと、サービスはShipmentオブジェクト(更新数量、更新日など)を適切に呼び出します。私は、Shipmentオブジェクトがどのような認可要件にも無関係であることを確かに知っています。一方、サービスオブジェクトに許可について知ってもらうことを望むなら、私は本当の把握はありません。これには良いパターンがありますか?

2)私の問題は実際には悪いデザインの症状ですか? ShipmentControllerの代わりに、StateAShipmentControllerとStateBShipmentControllerを用意する必要がありますか? Shipmentオブジェクトにはポリモーフィズムはありませんが(状態は列挙型です)、おそらくコントローラーがそれを反映するはずです。

私はもっと一般的な解決策を取っていると思いますが、私の場合は特定の解決策ではありません。私はその質問を説明するための例を提供したがっています。

ありがとうございます!

+0

出荷関連のものに対して独自の[Authorize]のようなアクションフィルタを作成してみませんか? –

+0

あなた自身の[Authorize]フィルタを構築することは本当に本当に悪い考えであり、ASP.NET MVC開発チームが本当に本当に本当に強く落胆させたものです –

+0

@Josh;同意しません。それは「本当に、本当に悪い考えではない」ということで、それはちょっとした注意を払って接近すべきである。私はそれを全く落胆させることについての公の記事を見たことがなく、いくつかの「本当に」と「強く」ではるかに少ない。私が知っている唯一の本物の「邪魔」は、フレームワークが提供するAuthorize属性を継承したいからです。そうすれば、正しい場所で確実に起動できるようになるからです。 – Paul

答えて

2

あなたの認可属性は、「出荷から出荷」アクションパラメータを取得したり、データをルーティングしてから決定することができます。

番号1には、ドメインオブジェクトで豊富な動作を可能にする多数のパターンがあります。二重ディスパッチでは、オブジェクトのメソッドへのサービス抽象化(インタフェース)への参照を渡します。それから、そのことをすることができます。また、出荷を受け取り、作業を行うアプリケーションサービスを作成することもできます。

番号2では、必ずしもそうではありません。 「コンテクスト・シップメント」のコンセプトを、あなたが入っているシップメント・コンテキストを把握するサービスに抽象化する必要があるかもしれません。

1

Rhino.Securityをご覧ください。このシナリオでは、ユーザー権限を実装するために使用できます。

3

アクションメソッドでそれ以降の権限チェックを行っても問題は発生しません。あなたは、あなたが探しているきめ細かな認証のために、ロールプロバイダを活用することができます。ここで私の構文を許してください - それはおそらく荒いと私はこれをテストしていない。

[Authorize(Roles="Shipping, Accounting")] 
public ActionResult Edit(int id) 
{ 
    Shipment shipment = repos.GetShipment(id); 


    switch (shipment.State) 
    { 
     case ShipmentState.A: 
     if (Roles.IsUserInRole("Shipping")) 
       return View(shipment); 
     else 
       return View("NotAuthorized"); 
     break; 
     case ShipmentState.B: 
     if (Roles.IsUserInRole("Accounting")) 
       return View(shipment); 
     else 
       return View("NotAuthorized"); 
     break; 
     default: 
       return View("NotAuthorized"); 
    } 
} 
+0

それは "単純な"解決策ですが、それはちょっと匂いがします。コントローラーの認可をハードコーディングすることはSRPに違反し、少なくともそれ自身のクラスにリファクタリングする必要があります。 –

+0

この例では、ほとんどの場合、状態パターンの実装が叫ばれています。 – Paul

+1

確かにそうですね!単純なように、私はOPの質問に対処することを確認したいと思った。 –

1

上記の回答に加えて、NotAuthorizedの独自のビューを作成する代わりに、HttpUnauthorizedResultを返すことができます。これはログインページにリダイレクトされ、通常の[Authorize]属性と同じように動作します

関連する問題