web-dev-qa-db-ja.com

次の場合にカスタムAuthorize属性を実装する方法は?

だから私は私のアクションメソッドを持っています

[Authorize(Roles="Admin")]
public ActionResult EditPosts(int id)
{
    return View();
}

私の場合、管理者が投稿を編集できるように管理者を承認する必要がありますが、(ここでクールな部分があります)、投稿の作成者が通常のユーザーである投稿を編集できるようにする必要もあります。投稿を作成したユーザーと管理者を除外し、他のユーザーを無許可のままにするにはどうすればよいですか?ルートパラメータとしてPostEntry IDを受け取っていますが、属性と属性が定数パラメータのみを受け入れた後、非常に難しいように見えます。あなたの答えは大歓迎です、乾杯!

31
Freeman

カスタム許可属性を作成できます。

public class AuthorizeAdminOrOwnerOfPostAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            // The user is not authenticated
            return false;
        }

        var user = httpContext.User;
        if (user.IsInRole("Admin"))
        {
            // Administrator => let him in
            return true;
        }

        var rd = httpContext.Request.RequestContext.RouteData;
        var id = rd.Values["id"] as string;
        if (string.IsNullOrEmpty(id))
        {
            // No id was specified => we do not allow access
            return false;
        }

        return IsOwnerOfPost(user.Identity.Name, id);
    }

    private bool IsOwnerOfPost(string username, string postId)
    {
        // TODO: you know what to do here
        throw new NotImplementedException();
    }
}

次に、コントローラーアクションをそれで装飾します。

[AuthorizeAdminOrOwnerOfPost]
public ActionResult EditPosts(int id)
{
    return View();
}
59
Darin Dimitrov

私はあなたがすでに答えを受け入れていることを理解しており、これはしばらく前に投稿されました。(btw:カスタム属性を追加するための優れた答え)、しかし、私は以下を指摘します:

この属性を1回使用している場合。単一のメソッド。これは良い実装ではありません。代わりに次のものが必要です。

[Authorize]   // Just make sure they are auth'ed at all.
public ActionResult EditPosts(int id)
{
    Post SomePost = findPostByID (id);   // However you do it - single lookup of post

    if (!user.IsInRole("Admin") &&  !{IsOwnerOfPost(post)} )  Return Not Authorized

  ... Edit post code here
}

これには次の利点があります。

  1. 誰かが後でそれがどこで使用されるのか不思議に思うであろう追加のクラスはありません。
  2. 他で使用できないクラスはありません(カスタム属性で再利用できません)
  3. パフォーマンスが向上:投稿の単一取得
  4. 誰かがそれがどのように機能するかを読んだり図にしたりするのがずっと簡単です。追跡する魔法のコードはありません。
  5. そして数年後、HttpContextBaseクラスが存在しない場合、またはIdパラメーターを取得するために使用されるトリックの他の部分がなくなった場合でも、コードは機能します...
6
Traderhut Games