78

コントローラーとアクションの両方に Authorize 属性がある場合、どちらが有効になりますか? それとも両方が有効になりますか?

4

4 に答える 4

166

あなたは尋ねました:

コントローラーとアクションの両方に Authorize 属性がある場合、どちらが有効になりますか? 両方?

これに簡単に答えると、両方です。その効果はAND、2 つの制限を一緒にすることです。その理由を以下で説明します...

詳細

したがって、これを尋ねる理由はいくつかあります。

  1. メソッドと比較してアクションに追加の制約を適用する方法を知りたいです。例えば
    • コントローラ レベルで、ユーザーにロール「user」を強制します。
    • アクション レベルで、「管理者」ロールのユーザーを追加で強制します。
  2. アクションレベルでコントローラの制約を置き換えたい
  3. アクション レベルでコントローラーの制約を削除し、メソッドを匿名ユーザーが使用できるようにしたい

MVC のバージョンが指定されていないため、現時点で最新 (MVC 4.5) であると想定します。ただし、MVC 3 を使用していたとしても、答えはあまり変わりません。

[Anonymous]コントローラーをオーバーライドする[Authorize](ケース 3)

ケース 3. (の使用) をカバーする必要はありません。これは、SO全体およびWeb 全体で[AllowAnonymous]既に回答されているためです。言うまでもありませんが、アクションを指定すると、コントローラーがそのアクションを持っていても、そのアクションが公開されます。[AllowAnonymous][Authorize]

また、グローバル フィルター を使用してWeb サイト全体を承認の対象にしAllowAnonymous、公開したいいくつかのアクションまたはコントローラーで使用することもできます。

[Authorize]相加的 (ケース 1)

ケース1は簡単です。例として、次のコントローラーを取り上げます。

[Authorize(Roles="user")]
public class HomeController : Controller {
    public ActionResult AllUsersIndex() {
        return View();
    }

    [Authorize(Roles = "admin")]
    public ActionResult AdminUsersIndex() {
        return View();
    }
}

デフォルト[Authorize(Roles="user")]では、コントローラー内のすべてのアクションを「ユーザー」ロールのアカウントのみが使用できるようにします。したがって、アクセスAllUsersIndexするには、「ユーザー」ロールに属している必要があります。ただし、アクセスAdminUsersIndexするには、「ユーザー」ロールと「管理者」ロールの両方にいる必要があります。例えば:

  • ユーザー名: ボブ、役割: ユーザー、 にはアクセスできませんAdminUsersIndexが、アクセスできますAllUsersIndex
  • ユーザー名: ジェーン、役割: 管理者、アクセスできないAdminUsersIndexまたはAllUsersIndex
  • ユーザー名: ティム、役割: ユーザーと管理者、アクセス可能AdminUsersIndexAllUsersIndex

これは、[Authorize]属性が付加的であることを示しています。これは属性のプロパティにも当てはまり、Usersと組み合わせRolesてさらに制限することができます。

この動作は、コントローラーとアクションの属性が機能する方法によるものです。アトリビュートは一緒にチェーンされ、オーダー コントローラーに適用されてからアクションに適用されます。最初のアクションが許可を拒否した場合、制御が返され、アクションの属性は呼び出されません。最初の認証が成功すると、2 番目の認証もチェックされます。この順序は、Order(たとえば[Authorize(Roles = "user", Order = 2)]) を指定することでオーバーライドできます。

オーバーライド[Authorize](ケース 2)

ケース 2 はよりトリッキーです。上記から、[Authorize]属性は (グローバル、次に) コントローラー、次にアクションの順序で検査されることを思い出してください。ユーザーが承認される資格がないことを最初に検出した人が勝ち、他の人は呼び出されません。

これを回避する 1 つの方法は、以下のように 2 つの新しい属性を定義することです。は[OverrideAuthorize]、 に従う以外に何もしません[Authorize]。その唯一の目的は、チェックできる型を定義することです。を使用[DefaultAuthorize]すると、リクエストで呼び出されているアクションが で装飾されているかどうかを確認できます[OverrideAuthorize]。そうである場合は、アクションの承認チェックを延期します。そうでない場合は、コントローラー レベルのチェックに進みます。

public class DefaultAuthorizeAttribute : AuthorizeAttribute {
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var action = filterContext.ActionDescriptor;
        if (action.IsDefined(typeof(OverrideAuthorizeAttribute), true)) return;

        base.OnAuthorization(filterContext);
    }
}
public class OverrideAuthorizeAttribute : AuthorizeAttribute {
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
    }
}

次に、次のように使用できます。

[DefaultAuthorize(Roles="user")]
public class HomeController : Controller {
    // Available to accounts in the "user" role
    public ActionResult AllUsersIndex() {
        return View();
    }
    // Available only to accounts both in the "user" and "admin" role
    [Authorize(Roles = "admin")]
    public ActionResult AdminUsersIndex() {
        return View();
    }
    // Available to accounts in the "superuser" role even if not in "user" role
    [OverrideAuthorize(Roles = "superuser")]
    public ActionResult SuperusersIndex() {
        return View();
    }
}

上記の例SuperusersIndexでは、「ユーザー」ロールを持っていなくても、「スーパーユーザー」ロールを持つアカウントで利用できます。

于 2013-05-23T11:58:49.443 に答える
2

コントローラーで使用すると、このコントローラーのすべてのメソッドが影響を受けます。

[Authorize]
public class SomeController(){

    // all actions are effected
    public ActionResult Action1
    public ActionResult Action2

これらのアクションのいずれかを防止したい場合は、次のようなものを使用できます。

[Authorize]
public class SomeController(){

    // all actions are effected
    public ActionResult Action1
    public ActionResult Action2

    [AllowAnonymous]
    public ActionResult Action3 // only this method is not effected...
于 2013-05-23T09:14:15.330 に答える