ASP.NET Core でカスタム AuthorizeAttribute を作成するにはどうすればいいですか? 質問する

ASP.NET Core でカスタム AuthorizeAttribute を作成するにはどうすればいいですか? 質問する

ASP.NET Coreでカスタム認証属性を作成しようとしています。以前のバージョンではオーバーライドが可能でしたbool AuthorizeCore(HttpContextBase httpContext)。しかし、これはもう存在しません。AuthorizeAttribute

カスタム AuthorizeAttribute を作成するための現在のアプローチは何ですか?

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

ベストアンサー1

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

ポリシー設計はフレームワークへの素晴らしい追加であり、その導入は ASP.Net Security Core チームに賞賛されるべきです。とはいえ、すべてのケースに適しているわけではありません。このアプローチの欠点は、特定のコントローラーまたはアクションに特定のクレーム タイプが必要であることを単純にアサートするという最も一般的なニーズに対して、便利なソリューションを提供できないことです。アプリケーションに、個々の REST リソースに対する CRUD 操作を管理する数百の個別のアクセス許可 ("CanCreateOrder"、"CanReadOrder"、"CanUpdateOrder"、"CanDeleteOrder" など) がある場合、新しいアプローチでは、ポリシー名とクレーム名の間の 1 対 1 のマッピングを繰り返し行うか (例options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));)、実行時にこれらの登録を実行するコード (例: データベースからすべてのクレーム タイプを読み取り、前述の呼び出しをループで実行する) を記述する必要があります。ほとんどの場合、このアプローチの問題は、不要なオーバーヘッドになることです。

ASP.Net Core セキュリティ チームは独自のソリューションを作成しないことを推奨していますが、場合によっては、これが開始するための最も賢明なオプションとなる場合があります。

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();
    }
}

おすすめ記事