Otorisasi Kustom di Asp.net WebApi - sungguh berantakan?

113

Saya membaca dari beberapa sumber (buku dan jawaban SO) tentang otorisasi di WebApi.

Misalkan saya ingin menambahkan Atribut Khusus yang memungkinkan akses hanya untuk Pengguna Tertentu:

Kasus 1

Saya telah melihat pendekatan overriding ini OnAuthorization , yang menetapkan respons jika ada yang salah

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 public override void OnAuthorization(HttpActionContext actionContext)
  {
   if ( /*check if user OK or not*/)
   {
     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
   }
  }
}

Kasus # 2

Tetapi saya juga melihat contoh serupa ini yang juga menimpa OnAuthorizationtetapi dengan panggilan ke base:

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
  base.OnAuthorization(actionContext);

    // If not authorized at all, don't bother

    if (actionContext.Response == null)  
     {
      //...
     }
}

Kemudian, Anda memeriksa apakah HttpActionContext.Responsesudah diatur atau tidak. Jika tidak disetel, itu berarti permintaan tersebut diotorisasi dan pengguna baik-baik saja

Kasus # 3

Tetapi saya juga telah melihat pendekatan pengesampingan ini IsAuthorized :

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 protected override bool IsAuthorized(HttpActionContext context)
  {
   if ( /*check if user OK or not*/)
   {
    return true;// or false
   }
  }
}

Kasus # 4

Dan kemudian saya melihat contoh serupa tetapi dengan call base.IsAuthorized (konteks):

protected override bool IsAuthorized(HttpActionContext context)
{
 if (something1 && something2 && base.IsAuthorized(context)) //??
 return true;
 return false;
}

Satu hal lagi

Dan akhirnya Dominick berkata di sini :

Anda tidak boleh mengganti OnAuthorization - karena Anda akan kehilangan penanganan [AllowAnonymous].

Pertanyaan

  • 1) Metode apa yang harus saya gunakan: IsAuthorizedatau OnAuthorization? (atau kapan harus menggunakan yang mana)

  • 2) kapan saya harus memanggil base.IsAuthorized orbase.OnAuthorization`?

  • 3) Apakah ini cara mereka membangunnya? bahwa jika responsnya nol maka semuanya baik-baik saja? (kasus # 2)

NB

Harap perhatikan, saya menggunakan (dan ingin menggunakan) hanya AuthorizeAttributeyang sudah mewarisi dari AuthorizationFilterAttribute

Kenapa?

Karena saya berada di tahap pertama dalam: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

masukkan deskripsi gambar di sini

Pokoknya saya bertanya melalui memperluas atribut Otorisasi.

Royi Namir
sumber
Apa yang Anda perlukan untuk mengganti atribut Otorisasi? Apa kasus penggunaan yang ingin Anda capai? Jika Anda perlu mengizinkan akses untuk pengguna tertentu mengapa tidak menggunakan atribut [Otorisasi (Pengguna = "Admin")] seperti ini?
Taiseer Joudeh
1
@TaiseerJoudeh Misalnya Cobalah untuk mengotorisasi pengguna antara pukul 10:00 hingga 12:00 (dapat dikonfigurasi). Anda tidak dapat melakukannya dengan Peran biasa dan atribut resmi. Anda harus membuat logika Anda sendiri
Royi Namir

Jawaban:

93

Metode mana yang harus saya gunakan: IsAuthorized atau OnAuthorization? (atau kapan harus menggunakan yang mana)

Anda akan memperpanjang AuthorizationFilterAttributejika logika otorisasi Anda tidak bergantung pada identitas dan peran yang ditetapkan. Untuk otorisasi terkait pengguna, Anda akan memperpanjang dan menggunakan AuthorizeAttribute. Untuk kasus sebelumnya, Anda akan menimpa OnAuthorization. Untuk kasus terakhir, Anda akan menimpa IsAuthorized. Seperti yang Anda lihat dari kode sumber atribut ini, OnAuthorizationditandai virtual untuk Anda timpa jika Anda berasal dari AuthorizationFilterAttribute. Di sisi lain, IsAuthorizedmetode ini ditandai sebagai virtual in AuthorizeAttribute. Saya yakin ini adalah penunjuk yang baik untuk penggunaan yang dimaksudkan.

kapan saya harus memanggil base.IsAuthorized atau base.OnAuthorization?

Jawaban atas pertanyaan ini terletak pada cara kerja OO secara umum. Jika Anda mengganti metode, Anda dapat sepenuhnya memberikan implementasi baru atau mendukung implementasi yang disediakan oleh induk dan menyempurnakan perilakunya. Misalnya, ambil kasus IsAuthorized(HttpActionContext). Perilaku kelas dasar adalah untuk memeriksa pengguna / peran terhadap apa yang ditentukan dalam filter vs identitas yang ditetapkan. Katakanlah, Anda ingin melakukan semua itu tetapi sebagai tambahan, Anda ingin memeriksa sesuatu yang lain, mungkin berdasarkan header permintaan atau sesuatu. Jika demikian, Anda dapat memberikan penggantian seperti ini.

protected override bool IsAuthorized(HttpActionContext actionContext)
{
    bool isAuthroized = base.IsAuthorized(actionContext);
    // Here you look at the header and do your additional stuff based on actionContext
    // and store the result in isRequestHeaderOk
    // Then, you can combine the results
    // return isAuthorized && isRequestHeaderOk;
}

Saya minta maaf, tapi tidak mengerti Q3 Anda. BTW, filter Otorisasi telah ada sejak lama dan orang menggunakannya untuk segala macam hal dan terkadang juga salah.

Satu hal lagi. Dan akhirnya ada orang di sini yang berkata: Anda tidak boleh menimpa OnAuthorization - karena Anda akan kehilangan penanganan [AllowAnonymous].

Orang yang mengatakan itu adalah Dewa kendali akses - Dominick. Jelas itu akan benar. Jika Anda melihat implementasi OnAuthorization(disalin di bawah),

public override void OnAuthorization(HttpActionContext actionContext)
{
    if (actionContext == null)
    {
        throw Error.ArgumentNull("actionContext");
    }

    if (SkipAuthorization(actionContext))
    {
        return;
    }

    if (!IsAuthorized(actionContext))
    {
        HandleUnauthorizedRequest(actionContext);
    }
}

panggilan ke SkipAuthorizationadalah bagian yang memastikan AllowAnonymousfilter diterapkan, yaitu, otorisasi dilewati. Jika Anda mengesampingkan metode ini, Anda kehilangan perilaku itu. Sebenarnya, jika Anda memutuskan untuk mendasarkan otorisasi Anda pada pengguna / peran, pada saat itu Anda akan memutuskan untuk mendapatkannya AuthorizeAttribute. Hanya opsi yang benar yang tersisa untuk Anda pada saat itu yang akan menimpa IsAuthorizeddan bukan yang sudah diganti OnAuthorization, meskipun secara teknis dimungkinkan untuk melakukannya.

PS. Di ASP.NET Web API, ada filter lain yang disebut filter otentikasi. Idenya adalah Anda menggunakannya untuk otentikasi dan otorisasi filter untuk otorisasi, seperti namanya. Namun, ada banyak contoh di mana batasan ini dipalsukan. Banyak contoh filter authroization akan melakukan semacam otentikasi. Bagaimanapun, jika Anda punya waktu dan ingin memahami lebih banyak, lihat artikel MSDN ini . Penafian: Itu ditulis oleh saya.

Badri
sumber
Terima kasih lagi, tetapi jika saya membaca yang tersirat, IsAuthenticated dipanggil oleh OnAuthirization, jadi mengapa tidak menimpa OnAuthorization dan memanggil base.OnAuthorization dan kemudian memeriksa tanggapan?
Royi Namir
Anda pasti bisa, jika itu yang Anda inginkan.
Badri
Dalam pertanyaan ketiga saya yang saya maksud: setelah menjalankan fungsi dasar - misalnya base.OnAuthorization, apakah satu-satunya cara untuk memeriksa apakah berhasil- adalah dengan memeriksa properti Respon ?, ps contohnya dari buku Anda :-)
Royi Namir
Ya, biasanya Anda mencari kode status 401 tetapi tidak null, setahu saya. BTW, saya tidak ingat pernah menulis tentang menimpa OnAuthorizationdi buku saya. Saya yakin saya tidak akan menulis tentang memeriksa tanggapan untuk null, karena ini adalah pertama kalinya saya mendengarnya :)
Badri
Ya saya sempat bingung dengan buku yang lain. Saya membaca 3 buku secara bersamaan: securty (milik Anda), praktis (milik Anda) dan webapi pro (Tugberk, Zeitler, Ali). Seperti yang Anda lihat - mereka melakukannya di sana: i.stack.imgur.com/LNGi4.jpg - mereka hanya memeriksa apakah null, jadi haruskah saya memeriksa kode null atau error?
Royi Namir
18

Oke, saran saya adalah melakukan hal berikut dengan asumsi bahwa Anda menggunakan token pembawa OAuth untuk melindungi API Web Anda dan Anda menyetel allowTime sebagai klaim untuk pengguna saat Anda mengeluarkan token. Anda dapat membaca lebih lanjut tentang otentikasi berbasis token di sini

  1. Buat CustomAuthorizeAttribute yang berasal dari AuthorizationFilterAttribute
  2. ganti metode OnAuthorizationAsyncdan gunakan kode contoh di bawah ini:

     public class CustomAuthorizeAttribute : AuthorizationFilterAttribute
    {
    
        public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
    
            var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;
    
            if (!principal.Identity.IsAuthenticated)
            {
                return Task.FromResult<object>(null);
            }
    
            var userName = principal.FindFirst(ClaimTypes.Name).Value;
            var userAllowedTime = principal.FindFirst("userAllowedTime").Value;
    
            if (currentTime != userAllowedTime)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla");
                return Task.FromResult<object>(null);
            }
    
            //User is Authorized, complete execution
            return Task.FromResult<object>(null);
    
        }
    }
  3. Sekarang di pengontrol Anda, Anda menggunakan atribut CustomAuthorize untuk melindungi pengontrol Anda menggunakan logika otorisasi ini.
Taiseer Joudeh
sumber
1
Terima kasih. Tapi saat ini saya menggunakan AuthorizeAttributeyang mewarisi AuthorizationFilterAttributedan -juga untuk belajar saya secara khusus bertanya tentang metode mana yang harus saya gunakan dan tentang Respon memiliki konten atau tidak ...
Royi Namir
3

ASP.NET v5 Memperkenalkan Sistem Otorisasi yang benar-benar baru. Bagi mereka yang akan Menggunakan NET 5 saya sarankan pindah ke Microsoft.AspNet.Authorization.

Cukup banyak itu menyelesaikan kekacauan yang disebabkan oleh menjaga keduanya System.Web.Http.Authorizedan System.Web.Mvc.Authorizedan implementasi otentikasi lama lainnya.

Ini memberikan abstraksi yang sangat baik dari Jenis Tindakan (Buat, Baca, Perbarui, Hapus), Sumber Daya, Peran, Klaim, Tampilan, Persyaratan Kustom dan memungkinkan untuk membangun Penangan kustom, menggabungkan salah satu dari yang di atas. Selain itu, penangan tersebut juga dapat digunakan dalam kombinasi.

Dalam ASP.NET v5, otorisasi sekarang menyediakan peran deklaratif sederhana dan model berbasis kebijakan yang lebih kaya di mana otorisasi dinyatakan dalam persyaratan dan penangan mengevaluasi klaim pengguna terhadap persyaratan. Pemeriksaan imperatif dapat didasarkan pada kebijakan atau kebijakan sederhana yang mengevaluasi identitas pengguna dan properti sumber daya yang coba diakses pengguna.

Anestis Kivranoglou
sumber
14
Senang mengetahui, tetapi tidak menjawab pertanyaan itu sama sekali.
Zero3