MembacaKonteks OtorisasiFilter dalam api netcore 3.1

9

Saya memiliki proyek netcore 2.2 yang berfungsi di mana saya telah menerapkan kebijakan khusus yang memeriksa Kunci API.

Di startup.cs saya menambahkan kebijakan ini seperti ini

//Add Key Policy
services.AddAuthorization(options =>
{
    options.AddPolicy("AppKey", policy => policy.Requirements.Add(new AppKeyRequirement()));
});

Di AppKeyRequirement saya, saya mewarisi dari AuthorizationHandler dan menyelesaikan kunci dalam permintaan yang masuk seperti ini

protected override Task HandleRequirementAsync(AuthorizationHandlerContext authContext, AppKeyRequirement requirement)
{
    var authorizationFilterContext = (AuthorizationFilterContext)authContext.Resource;
    var query = authorizationFilterContext.HttpContext.Request.Query;

    if (query.ContainsKey("key") && query.ContainsKey("app"))
    { // Do stuff

Ini tidak berfungsi di netcore 3.1

Saya mendapatkan kesalahan berikut:

Tidak dapat membuang objek bertipe 'Microsoft.AspNetCore.Routing.RouteEndpoint' untuk mengetik 'Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext'.

Apa cara yang benar untuk melakukan ini di inti 3 dan di atas?

Seperti yang ditunjukkan oleh Kirk Larkin, cara yang benar dalam .net 3.0 dan di atasnya adalah menyuntikkan IHttpContextAccessor ke dalam Auth handler dan menggunakannya.

Pertanyaan saya pada titik ini adalah bagaimana saya menyuntikkan ini? Saya tidak bisa meneruskan ini di startup.cs atau setidaknya saya tidak melihat caranya.

Setiap ide / petunjuk akan sangat dihargai.

w2olves
sumber

Jawaban:

14

Dalam versi sebelum ASP.NET Core 3.0, implementasi dari IAuthorizationHandler dipanggil selama pipa MVC. Di 3.0 dan seterusnya, yang menggunakan endpoint-routing (secara default), implementasi ini dipanggil oleh middleware otorisasi ( UseAuthorization()). Middleware ini berjalan sebelum pipeline MVC, bukan sebagai bagian dari itu.

Perubahan ini berarti itu AuthorizationFilterContext tidak lagi diteruskan ke penangan otorisasi. Alih-alih, ini merupakan contoh dari RouteEndpoint, yang tidak menyediakan akses ke HttpContext.

Dalam contoh Anda, Anda hanya menggunakan AuthorizationFilterContextuntuk mendapatkan HttpContext. Di 3.0+, suntikkanIHttpContextAccessor ke penangan otorisasi Anda dan gunakan itu. Berikut ini contoh untuk kelengkapan:

public class AppKeyAuthorizationHandler : AuthorizationHandler<AppKeyRequirement>
{
    private readonly IHttpContextAccessor httpContextAccessor;

    public AppKeyAuthorizationHandler(IHttpContextAccessor httpContextAccessor)
    {
        this.httpContextAccessor = httpContextAccessor;
    }

    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext authContext, AppKeyRequirement requirement)
    {
        var httpContext = httpContextAccessor.HttpContext;
        var query = httpContext.Request.Query;

        if (query.ContainsKey("key") && query.ContainsKey("app"))
        {
            // ...
        }
    }
}

Anda juga mungkin harus mendaftar IHttpContextAccessordiConfigureServices :

services.AddHttpContextAccessor();

Lihat Menggunakan HttpContext dari komponen khusus untuk informasi lebih lanjut tentang penggunaan IHttpContextAccessor.

Kirk Larkin
sumber
1
Terima kasih atas petunjuk ini. Saya mencoba membuat kebijakan di mana jika kunci API tidak ada, panggilan akan ditolak. Bisakah kita tidak lagi menggunakan // Menambahkan layanan Kebijakan Utama.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (AppKeyRequirement baru ()));}); Jika tidak, bagaimana saya bisa mencegat panggilan sebelum menyentuh tindakan pengontrol?
w2Solves
1
Ya, itu masih berfungsi sama seperti sebelumnya.
Kirk Larkin
Konstruktor mengharapkan IHttpContextAccessor bagaimana saya bisa meneruskan ini ketika saya membuat kebijakan di Startup.cs? services.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (AppKeyRequirement baru ()));}); Saya juga dapat membuat konstruktor default baru untuk AppKeyAuthorizationHandler tetapi kemudian httpContextAccessor.HttpContext; adalah null saat ada permintaan. Ada gagasan?
w2Solves
1
Anda menambahkan handler Anda menggunakan DI, yang membuat instance untuk Anda dan meneruskan di IHttpContextAccessor. Lihat dokumen .
Kirk Larkin