Otorisasi sederhana di ASP.NET Core

Otorisasi di ASP.NET Core dikontrol dengan AuthorizeAttribute dan berbagai parameternya. Dalam bentuknya yang paling mendasar, menerapkan [Authorize] atribut ke pengontrol, tindakan, atau Razor Halaman, membatasi akses ke komponen tersebut ke pengguna yang diautentikasi.

Kode berikut membatasi akses ke pengguna yang diautentikasi AccountController :

[Authorize]
public class AccountController : Controller
{
    public ActionResult Login()
    {
    }

    public ActionResult Logout()
    {
    }
}

Jika Anda ingin menerapkan otorisasi ke tindakan daripada pengontrol, terapkan AuthorizeAttribute atribut ke tindakan itu sendiri:

public class AccountController : Controller
{
   public ActionResult Login()
   {
   }

   [Authorize]
   public ActionResult Logout()
   {
   }
}

Sekarang hanya pengguna terautentikasi yang Logout dapat mengakses fungsi.

Anda juga dapat menggunakan AllowAnonymous atribut untuk mengizinkan akses oleh pengguna yang tidak diautentikasi ke tindakan individual. Contohnya:

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()
    {
    }

    public ActionResult Logout()
    {
    }
}

Ini hanya akan memungkinkan pengguna terautentikasi ke AccountController, kecuali untuk Login tindakan, yang dapat diakses oleh semua orang, terlepas dari status mereka yang diautentikasi atau tidak diautentikasi / anonim.

Peringatan

[AllowAnonymous] melewati semua pernyataan otorisasi. Jika Anda menggabungkan [AllowAnonymous] dan atribut apa pun [Authorize] , [Authorize] atribut akan diabaikan. Misalnya jika Anda menerapkan [AllowAnonymous] pada tingkat pengontrol, atribut apa pun [Authorize] pada pengontrol yang sama (atau pada tindakan apa pun di dalamnya) diabaikan.

Kode berikut membatasi akses ke LogoutModelRazor Halaman untuk pengguna yang diautentikasi:

[Authorize]
public class LogoutModel : PageModel
{
    public async Task OnGetAsync()
    {

    }

    public async Task<IActionResult> OnPostAsync()
    {

    }
}

Untuk informasi tentang cara mengharuskan semua pengguna diautentikasi secara global, lihat Memerlukan pengguna yang diautentikasi.

Mengotorisasi atribut dan Razor Halaman

AuthorizeAttributeTidak dapat diterapkan ke Razor penangan Halaman. Misalnya, [Authorize] tidak dapat diterapkan ke OnGet, , OnPostatau handler halaman lainnya. Pertimbangkan untuk menggunakan pengontrol ASP.NET Core MVC untuk halaman dengan persyaratan otorisasi yang berbeda untuk penangan yang berbeda. Menggunakan pengontrol MVC saat persyaratan otorisasi yang berbeda diperlukan:

  • Adalah pendekatan yang paling tidak kompleks.
  • Adalah pendekatan yang direkomendasikan oleh Microsoft.

Jika Anda memutuskan untuk tidak menggunakan pengontrol MVC, dua pendekatan berikut dapat digunakan untuk menerapkan otorisasi ke Razor metode handler Halaman:

  • Gunakan halaman terpisah untuk penangan halaman yang memerlukan otorisasi yang berbeda. Pindahkan konten bersama ke dalam satu atau beberapa tampilan parsial. Jika memungkinkan, ini adalah pendekatan yang disarankan.

  • Untuk konten yang harus berbagi halaman umum, tulis filter yang melakukan otorisasi sebagai bagian dari IAsyncPageFilter.OnPageHandlerSelectionAsync. Proyek PageHandlerAuth GitHub menunjukkan pendekatan ini:

    [TypeFilter(typeof(AuthorizeIndexPageHandlerFilter))]
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;
    
        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }
    
        public void OnGet()
        {
    
        }
    
        public void OnPost()
        {
    
        }
    
        [AuthorizePageHandler]
        public void OnPostAuthorized()
        {
    
        }
    }
    
    public class AuthorizeIndexPageHandlerFilter : IAsyncPageFilter, IOrderedFilter
    {
        private readonly IAuthorizationPolicyProvider policyProvider;
        private readonly IPolicyEvaluator policyEvaluator;
    
        public AuthorizeIndexPageHandlerFilter(
            IAuthorizationPolicyProvider policyProvider,
            IPolicyEvaluator policyEvaluator)
        {
            this.policyProvider = policyProvider;
            this.policyEvaluator = policyEvaluator;
        }
    
        // Run late in the selection pipeline
        public int Order => 10000;
    
        public Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) => next();
    
        public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
        {
            var attribute = context.HandlerMethod?.MethodInfo?.GetCustomAttribute<AuthorizePageHandlerAttribute>();
            if (attribute is null)
            {
                return;
            }
    
            var policy = await AuthorizationPolicy.CombineAsync(policyProvider, new[] { attribute });
            if (policy is null)
            {
                return;
            }
    
            await AuthorizeAsync(context, policy);
        }
    
        #region AuthZ - do not change
        private async Task AuthorizeAsync(ActionContext actionContext, AuthorizationPolicy policy)
        {
            var httpContext = actionContext.HttpContext;
            var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, httpContext);
            var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, httpContext, actionContext.ActionDescriptor);
            if (authorizeResult.Challenged)
            {
                if (policy.AuthenticationSchemes.Count > 0)
                {
                    foreach (var scheme in policy.AuthenticationSchemes)
                    {
                        await httpContext.ChallengeAsync(scheme);
                    }
                }
                else
                {
                    await httpContext.ChallengeAsync();
                }
    
                return;
            }
            else if (authorizeResult.Forbidden)
            {
                if (policy.AuthenticationSchemes.Count > 0)
                {
                    foreach (var scheme in policy.AuthenticationSchemes)
                    {
                        await httpContext.ForbidAsync(scheme);
                    }
                }
                else
                {
                    await httpContext.ForbidAsync();
                }
    
                return;
            }
        }
    

Peringatan

Pendekatan sampel PageHandlerAuthtidak:

  • Buat dengan atribut otorisasi yang diterapkan ke halaman, model halaman, atau secara global. Menyusun atribut otorisasi menghasilkan autentikasi dan otorisasi yang dijalankan beberapa kali ketika Anda memiliki satu lagi AuthorizeAttribute atau AuthorizeFilter instans juga diterapkan ke halaman.
  • Bekerja bersama dengan sistem autentikasi dan otorisasi Inti ASP.NET lainnya. Anda harus memverifikasi menggunakan pendekatan ini berfungsi dengan benar untuk aplikasi Anda.

Tidak ada rencana untuk mendukung penangan AuthorizeAttribute Halaman Razor .