2012-04-26 5 views
1

私はこれに関する多くの経験がありません。皆さんから良い提案を得ることを本当に願っています。私は次のセキュリティシナリオを実装する必要があり、それを実行する最善の方法を知りたいと思います。ASP.NET MVCでのカスタムセキュリティシナリオ

従業員、監督者、部長がいるとします。 従業員と監督者の両方に、自分が属している部門マネージャを指し示しているManagerIdが割り当てられています。

スーパーバイザーユーザーがログインすると、彼と同じマネージャーIDに属する従業員のレコードのみが表示されるようにします。 ManagerId!=従業員のManagerIdがアクセスしたいので、別のManagerIdユーザーの別の監督者がログインして、他の従業員の情報をurl(例:wwww.domain.com/employee/details/{id})に手動でパンチすると、 制限される。

意味がありますか?

public ActionResult Details(int id) 
{ 
    var employee = employeeRepository.Get(id) 
    var user = (CustomIdentity)ControllerContext.HttpContext.User.Identity; 

    if(employee.managerId == user.managerId) 
    { 
     Do whatever... 
    } 
    else  
    { 
     Not allowed 
    } 
} 

しかし、すべてActionMethodsでそれを入力すると冗長なようだとjust..ehh ...私はより良い方法があるに違いありません知っている:

は私のようなすべてのActionMethodsにチェックを入力し始めました。

答えて

2

ここに解決策のスタブがあります。それは少しのクリーンアップが必要ですが、必要なものすべてを提供する必要があります。

カスタムActionFilterを作成し、それにメソッドを装飾します。

[ManagerIdAuthentication] 
public ActionResult Details(int id) 
{ 
    // Gets executed if the filter allows it to go through. 
} 

次のクラスは、この検証が必要なすべての操作に含めることができるように、別のライブラリに作成することができます。

public class ManagerIdAuthentication : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     // the next line needs improvement, only works on an httpGet since retrieves 
     // the id from the url. Improve this line to obtain the id regardless of 
     // the method (GET, POST, etc.) 
     var id = filterContext.HttpContext.Request.QueryString["id"]; 

     var employee = employeeRepository.Get(id); 
     var user = filterContext.HttpContext.User.Identity; 
     if (employee.managerId == user.managerId) 
     { 
      var res = filterContext.HttpContext.Response; 
      res.StatusCode = 402; 
      res.End(); 
      filterContext.Result = new EmptyResult(); //may use content result if want to provide additional info in the error message. 
     } 
     else 
     { 
      // OK, let it through. 
     } 
    } 
} 
+0

ありがとうございます。とても興味深い。 ここには本当に「Else」が必要ですか? If(employee.managerId!= user。)とは言えません。managerId) 新しいMyUnauthorizedException()をスローします。 ...そうしないと、これを実装するメソッドがトリガーされます。いいえ?私は何が欠けていますか? (employee.managerId == user.managerId)ステートメントの場合は、あなたが持っているものの要点は何ですか? – Shenaniganz

+0

elseの必要はありません...実行を継続するという点を確認するだけです。 – agarcian

2

私はこれまで同様の問題を抱えていましたが、オブジェクト単位のアクセス許可と考えていました。 、そして、

public bool CanUserAccess(User user) { 
    return managerId == user.managerId; 
} 

制御リソースへのアクセスを提供、各アクションの先頭に:私がやったことと類似したオブジェクトにメンバーを追加した

public ActionResult Details(int id) 
{ 
    var employee = employeeRepository.Get(id) 
    var user = (CustomIdentity)ControllerContext.HttpContext.User.Identity; 
    if(!employee.CanUserAccess(user)) 
     return new HttpUnauthorizedResult(); 

    // Normal logic here 
} 

をそれは確かに完璧ではないですが、それがありません許可の処理を一元化し、将来の複雑さを簡単に増やすことができます(チェーンへのアクセスを許可する、HRの特別なルールなど)。 User.Identityプロパティにアクセスしてもう少し自動化する(または少なくとも型変換を処理する)ために、別のオーバーロード/拡張機能を記述することもできます。

私はACLを扱っていたので、アクションの基本的な性質(たとえば、読み込み、書き込み、削除、作成など)を指定する追加のメソッド/パラメータが必要でした。

+0

私のIFロジックを別のステートメントにすることを除いて、ほとんど同じことですか? – Shenaniganz

+0

基本的に。パーミッションチェックを一元化するだけでDRYがもう少しです。 'ActionFilterAttribute'アプローチはおそらくアプリケーションでうまくいくと仮定して最もクリーンなアプローチです。あなたはリポジトリにアクセスできる必要があります(それほど難しくありません)が、アクセスチェックにどのオブジェクトが使用されているのかを解読できる必要があります(難しいかもしれません)。 – antijon