1. ホーム
  2. c#

[解決済み] ASP.NET CoreでカスタムのAuthorizeAttributeを作成する方法は?

2022-03-17 09:27:22

質問

ASP.NET Coreでカスタム認可属性を作ろうとしています。 以前のバージョンでは bool AuthorizeCore(HttpContextBase httpContext) . しかし、これはもう AuthorizeAttribute .

AuthorizeAttributeをカスタムで作成する場合、現在どのような方法があるのでしょうか?

私が達成しようとしていること ヘッダー認証でセッションIDを受け取ります。そのIDから、特定のアクションが有効であるかどうかを知ることができます。

どのように解決するのですか?

ASP.Net Core チームが推奨するアプローチは、完全に文書化されている新しいポリシー設計を使用することです。 ここで . 新しいアプローチの背後にある基本的な考え方は、新しい [Authorize] 属性で指定します。 [Authorize( Policy = "YouNeedToBe18ToDoThis")] ここで、ポリシーはアプリケーションの Startup.cs を実行し、あるコードブロック (例えば、年齢が 18 歳以上であることを主張するユーザを確保する) を実行します。

ポリシー設計はフレームワークへの素晴らしい追加機能であり、ASP.Net Security Core チームはその導入を称賛されるべきです。 とはいえ、すべてのケースに適しているわけではありません。 このアプローチの欠点は、特定のコントローラやアクションが特定のクレームタイプを必要とするという、最も一般的なニーズに対して便利なソリューションを提供できないことです。 アプリケーションに、個々の REST リソースに対する CRUD 操作を制御する何百もの個別の権限 ("CanCreateOrder", "CanReadOrder", "CanUpdateOrder", "CanDeleteOrder" 等) がある場合、新しいアプローチはポリシー名と請求名間の一対一のマッピングの反復が必要か (e.g., etc.) です。 options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder)); または、実行時にこれらの登録を行うコードを記述する(例えば、データベースからすべての請求タイプを読み込んで、ループ内で前述の呼び出しを実行する)。 大半の場合、この方法の問題は、不必要なオーバーヘッドであることです。

ASP.Net Core Securityチームは、独自のソリューションを作成しないことを推奨していますが、場合によっては、これが最も賢明な選択肢となる可能性もあります。

以下は IAuthorizationFilter で、指定したコントローラやアクションに対する要求事項を簡単に表現できます。

public class ClaimRequirementAttribute : TypeFilterAttribute
{
    public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter))
    {
        Arguments = new object[] {new Claim(claimType, claimValue) };
    }
}

public class ClaimRequirementFilter : IAuthorizationFilter
{
    readonly Claim _claim;

    public ClaimRequirementFilter(Claim claim)
    {
        _claim = claim;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value);
        if (!hasClaim)
        {
            context.Result = new ForbidResult();
        }
    }
}


[Route("api/resource")]
public class MyController : Controller
{
    [ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")]
    [HttpGet]
    public IActionResult GetResource()
    {
        return Ok();
    }
}