Autentikasi dan otorisasi di gRPC untuk ASP.NET Core
Oleh James Newton-King
Menampilkan atau mengunduh kode sampel (cara mengunduh)
Mengautentikasi pengguna yang memanggil layanan gRPC
gRPC dapat digunakan dengan autentikasi ASP.NET Core untuk mengaitkan pengguna dengan setiap panggilan.
Berikut ini adalah contoh Program.cs
yang menggunakan autentikasi gRPC dan ASP.NET Core:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapGrpcService<GreeterService>();
Catatan
Urutan tempat Anda mendaftarkan middleware autentikasi ASP.NET Core penting. Selalu panggil UseAuthentication
dan UseAuthorization
sesudah UseRouting
dan sebelum UseEndpoints
.
Mekanisme autentikasi yang digunakan aplikasi Anda selama panggilan perlu dikonfigurasi. Konfigurasi autentikasi ditambahkan dan Program.cs
akan berbeda tergantung pada mekanisme autentikasi yang digunakan aplikasi Anda.
Setelah autentikasi disiapkan, pengguna dapat diakses dalam metode layanan gRPC melalui ServerCallContext
.
public override Task<BuyTicketsResponse> BuyTickets(
BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
// ... access data from ClaimsPrincipal ...
}
Autentikasi token pembawa
Klien dapat menyediakan token akses untuk autentikasi. Server memvalidasi token dan menggunakannya untuk mengidentifikasi pengguna.
Di server, autentikasi token pembawa dikonfigurasi menggunakan middleware Pembawa JWT.
Di klien .NET gRPC, token dapat dikirim dengan panggilan dengan menggunakan Metadata
koleksi. Entri dalam Metadata
koleksi dikirim dengan panggilan gRPC sebagai header HTTP:
public bool DoAuthenticatedCall(
Ticketer.TicketerClient client, string token)
{
var headers = new Metadata();
headers.Add("Authorization", $"Bearer {token}");
var request = new BuyTicketsRequest { Count = 1 };
var response = await client.BuyTicketsAsync(request, headers);
return response.Success;
}
Atur token pembawa dengan CallCredentials
Mengonfigurasi ChannelCredentials
pada saluran adalah cara alternatif untuk mengirim token ke layanan dengan panggilan gRPC. Dapat ChannelCredentials
mencakup CallCredentials
, yang menyediakan cara untuk mengatur Metadata
secara otomatis .
Manfaat menggunakan CallCredentials
:
- Autentikasi dikonfigurasi secara terpusat pada saluran. Token tidak perlu disediakan secara manual ke panggilan gRPC.
- Panggilan
CallCredentials.FromInterceptor
balik tidak sinkron. Kredensial panggilan dapat mengambil token kredensial dari sistem eksternal jika diperlukan. Metode asinkron di dalam panggilan balik harus menggunakanCancellationToken
padaAuthInterceptorContext
.
Catatan
CallCredentials
hanya diterapkan jika saluran diamankan dengan TLS. Mengirim header autentikasi melalui koneksi yang tidak aman memiliki implikasi keamanan dan tidak boleh dilakukan di lingkungan produksi. Aplikasi dapat mengonfigurasi saluran untuk mengabaikan perilaku ini dan selalu menggunakan CallCredentials
dengan mengatur UnsafeUseInsecureChannelCallCredentials
di saluran.
Info masuk dalam contoh berikut mengonfigurasi saluran untuk mengirim token dengan setiap panggilan gRPC:
private static GrpcChannel CreateAuthenticatedChannel(ITokenProvder tokenProvider)
{
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
{
var token = await tokenProvider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
});
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}
Token pembawa dengan pabrik klien gRPC
Pabrik klien gRPC dapat membuat klien yang mengirim token pembawa menggunakan AddCallCredentials
. Metode ini tersedia di Grpc.Net.ClientFactory versi 2.46.0 atau yang lebih baru.
Delegasi yang diteruskan ke AddCallCredentials
dijalankan untuk setiap panggilan gRPC:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});
Injeksi dependensi (DI) dapat dikombinasikan dengan AddCallCredentials
. Kelebihan beban diteruskan IServiceProvider
ke delegasi, yang dapat digunakan untuk membuat layanan dari DI menggunakan layanan tercakup dan sementara.
Pertimbangkan aplikasi yang memiliki:
- Ditentukan pengguna
ITokenProvider
untuk mendapatkan token pembawa.ITokenProvider
terdaftar di DI dengan masa pakai tercakup. - Pabrik klien gRPC dikonfigurasi untuk membuat klien yang disuntikkan ke layanan gRPC dan pengontrol API Web.
- Panggilan gRPC harus digunakan
ITokenProvider
untuk mendapatkan token pembawa.
public interface ITokenProvider
{
Task<string> GetTokenAsync(CancellationToken cancellationToken);
}
public class AppTokenProvider : ITokenProvider
{
private string _token;
public async Task<string> GetTokenAsync(CancellationToken cancellationToken)
{
if (_token == null)
{
// App code to resolve the token here.
}
return _token;
}
}
builder.Services.AddScoped<ITokenProvider, AppTokenProvider>();
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials(async (context, metadata, serviceProvider) =>
{
var provider = serviceProvider.GetRequiredService<ITokenProvider>();
var token = await provider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
}));
Kode sebelumnya:
ITokenProvider
Mendefinisikan danAppTokenProvider
. Jenis ini menangani penyelesaian token autentikasi untuk panggilan gRPC.- Mendaftarkan
AppTokenProvider
jenis dengan DI dalam masa pakai tercakup.AppTokenProvider
cache token sehingga hanya panggilan pertama dalam cakupan yang diperlukan untuk menghitungnya. - Mendaftarkan jenis dengan
GreeterClient
pabrik klien. AddCallCredentials
Mengonfigurasi untuk klien ini. Delegasi dijalankan setiap kali panggilan dilakukan dan menambahkan token yang dikembalikan olehITokenProvider
ke metadata.
Autentikasi sertifikat klien
Klien dapat menyediakan sertifikat klien untuk autentikasi. Autentikasi sertifikat terjadi di tingkat TLS, jauh sebelum ASP.NET Core. Ketika permintaan memasuki ASP.NET Core, paket autentikasi sertifikat klien memungkinkan Anda menyelesaikan sertifikat ke ClaimsPrincipal
.
Catatan
Konfigurasikan server untuk menerima sertifikat klien. Untuk informasi tentang menerima sertifikat klien di Kestrel, IIS, dan Azure, lihat Mengonfigurasi autentikasi sertifikat di ASP.NET Core.
Di klien .NET gRPC, sertifikat klien ditambahkan ke HttpClientHandler
yang kemudian digunakan untuk membuat klien gRPC:
public Ticketer.TicketerClient CreateClientWithCert(
string baseAddress,
X509Certificate2 certificate)
{
// Add client cert to the handler
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);
// Create the gRPC channel
var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
{
HttpHandler = handler
});
return new Ticketer.TicketerClient(channel);
}
Mekanisme autentikasi lainnya
Banyak mekanisme autentikasi yang didukung ASP.NET Core bekerja dengan gRPC:
- Microsoft Entra ID
- Sertifikat Klien
- IdentityServer
- JWT Token
- OAuth 2.0
- OpenID Connect
- WS-Federation
Untuk informasi selengkapnya tentang mengonfigurasi autentikasi di server, lihat autentikasi ASP.NET Core.
Mengonfigurasi klien gRPC untuk menggunakan autentikasi akan bergantung pada mekanisme autentikasi yang Anda gunakan. Contoh token pembawa dan sertifikat klien sebelumnya menunjukkan beberapa cara klien gRPC dapat dikonfigurasi untuk mengirim metadata autentikasi dengan panggilan gRPC:
- Klien gRPC yang sangat ditik menggunakan
HttpClient
secara internal. Autentikasi dapat dikonfigurasi pada HttpClientHandler, atau dengan menambahkan instans kustom HttpMessageHandler keHttpClient
. - Setiap panggilan gRPC memiliki argumen opsional
CallOptions
. Header kustom dapat dikirim menggunakan koleksi header opsi.
Catatan
Autentikasi Windows (NTLM/Kerberos/Negosiasi) tidak dapat digunakan dengan gRPC. gRPC memerlukan HTTP/2, dan HTTP/2 tidak mendukung Autentikasi Windows.
Mengotorisasi pengguna untuk mengakses layanan dan metode layanan
Secara default, semua metode dalam layanan dapat dipanggil oleh pengguna yang tidak diabaikan. Untuk memerlukan autentikasi, terapkan [Authorize]
atribut ke layanan:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}
Anda dapat menggunakan argumen konstruktor dan properti [Authorize]
atribut untuk membatasi akses hanya ke pengguna yang cocok dengan kebijakan otorisasi tertentu. Misalnya, jika Anda memiliki kebijakan otorisasi kustom yang disebut MyAuthorizationPolicy
, pastikan hanya pengguna yang cocok dengan kebijakan tersebut yang dapat mengakses layanan menggunakan kode berikut:
[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}
Metode layanan individual juga dapat [Authorize]
menerapkan atribut . Jika pengguna saat ini tidak cocok dengan kebijakan yang diterapkan ke metode dan kelas, kesalahan dikembalikan ke pemanggil:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
public override Task<AvailableTicketsResponse> GetAvailableTickets(
Empty request, ServerCallContext context)
{
// ... buy tickets for the current user ...
}
[Authorize("Administrators")]
public override Task<BuyTicketsResponse> RefundTickets(
BuyTicketsRequest request, ServerCallContext context)
{
// ... refund tickets (something only Administrators can do) ..
}
}
Sumber Daya Tambahan:
Menampilkan atau mengunduh kode sampel (cara mengunduh)
Mengautentikasi pengguna yang memanggil layanan gRPC
gRPC dapat digunakan dengan autentikasi ASP.NET Core untuk mengaitkan pengguna dengan setiap panggilan.
Berikut ini adalah contoh Startup.Configure
yang menggunakan autentikasi gRPC dan ASP.NET Core:
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});
}
Catatan
Urutan tempat Anda mendaftarkan middleware autentikasi ASP.NET Core penting. Selalu panggil UseAuthentication
dan UseAuthorization
sesudah UseRouting
dan sebelum UseEndpoints
.
Mekanisme autentikasi yang digunakan aplikasi Anda selama panggilan perlu dikonfigurasi. Konfigurasi autentikasi ditambahkan dan Startup.ConfigureServices
akan berbeda tergantung pada mekanisme autentikasi yang digunakan aplikasi Anda.
Setelah autentikasi disiapkan, pengguna dapat diakses dalam metode layanan gRPC melalui ServerCallContext
.
public override Task<BuyTicketsResponse> BuyTickets(
BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
// ... access data from ClaimsPrincipal ...
}
Autentikasi token pembawa
Klien dapat menyediakan token akses untuk autentikasi. Server memvalidasi token dan menggunakannya untuk mengidentifikasi pengguna.
Di server, autentikasi token pembawa dikonfigurasi menggunakan middleware Pembawa JWT.
Di klien .NET gRPC, token dapat dikirim dengan panggilan dengan menggunakan Metadata
koleksi. Entri dalam Metadata
koleksi dikirim dengan panggilan gRPC sebagai header HTTP:
public bool DoAuthenticatedCall(
Ticketer.TicketerClient client, string token)
{
var headers = new Metadata();
headers.Add("Authorization", $"Bearer {token}");
var request = new BuyTicketsRequest { Count = 1 };
var response = await client.BuyTicketsAsync(request, headers);
return response.Success;
}
Atur token pembawa dengan CallCredentials
Mengonfigurasi ChannelCredentials
pada saluran adalah cara alternatif untuk mengirim token ke layanan dengan panggilan gRPC. Dapat ChannelCredentials
mencakup CallCredentials
, yang menyediakan cara untuk mengatur Metadata
secara otomatis .
Manfaat menggunakan CallCredentials
:
- Autentikasi dikonfigurasi secara terpusat pada saluran. Token tidak perlu disediakan secara manual ke panggilan gRPC.
- Panggilan
CallCredentials.FromInterceptor
balik tidak sinkron. Kredensial panggilan dapat mengambil token kredensial dari sistem eksternal jika diperlukan. Metode asinkron di dalam panggilan balik harus menggunakanCancellationToken
padaAuthInterceptorContext
.
Catatan
CallCredentials
hanya diterapkan jika saluran diamankan dengan TLS. Mengirim header autentikasi melalui koneksi yang tidak aman memiliki implikasi keamanan dan tidak boleh dilakukan di lingkungan produksi. Aplikasi dapat mengonfigurasi saluran untuk mengabaikan perilaku ini dan selalu menggunakan CallCredentials
dengan mengatur UnsafeUseInsecureChannelCallCredentials
di saluran.
Info masuk dalam contoh berikut mengonfigurasi saluran untuk mengirim token dengan setiap panggilan gRPC:
private static GrpcChannel CreateAuthenticatedChannel(ITokenProvder tokenProvider)
{
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
{
var token = await tokenProvider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
});
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}
Token pembawa dengan pabrik klien gRPC
Pabrik klien gRPC dapat membuat klien yang mengirim token pembawa menggunakan AddCallCredentials
. Metode ini tersedia di Grpc.Net.ClientFactory versi 2.46.0 atau yang lebih baru.
Delegasi yang diteruskan ke AddCallCredentials
dijalankan untuk setiap panggilan gRPC:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});
Injeksi dependensi (DI) dapat dikombinasikan dengan AddCallCredentials
. Kelebihan beban diteruskan IServiceProvider
ke delegasi, yang dapat digunakan untuk membuat layanan dari DI menggunakan layanan tercakup dan sementara.
Pertimbangkan aplikasi yang memiliki:
- Ditentukan pengguna
ITokenProvider
untuk mendapatkan token pembawa.ITokenProvider
terdaftar di DI dengan masa pakai tercakup. - Pabrik klien gRPC dikonfigurasi untuk membuat klien yang disuntikkan ke layanan gRPC dan pengontrol API Web.
- Panggilan gRPC harus digunakan
ITokenProvider
untuk mendapatkan token pembawa.
public interface ITokenProvider
{
Task<string> GetTokenAsync(CancellationToken cancellationToken);
}
public class AppTokenProvider : ITokenProvider
{
private string _token;
public async Task<string> GetTokenAsync(CancellationToken cancellationToken)
{
if (_token == null)
{
// App code to resolve the token here.
}
return _token;
}
}
services.AddScoped<ITokenProvider, AppTokenProvider>();
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials(async (context, metadata, serviceProvider) =>
{
var provider = serviceProvider.GetRequiredService<ITokenProvider>();
var token = await provider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
}));
Kode sebelumnya:
ITokenProvider
Mendefinisikan danAppTokenProvider
. Jenis ini menangani penyelesaian token autentikasi untuk panggilan gRPC.- Mendaftarkan
AppTokenProvider
jenis dengan DI dalam masa pakai tercakup.AppTokenProvider
cache token sehingga hanya panggilan pertama dalam cakupan yang diperlukan untuk menghitungnya. - Mendaftarkan jenis dengan
GreeterClient
pabrik klien. AddCallCredentials
Mengonfigurasi untuk klien ini. Delegasi dijalankan setiap kali panggilan dilakukan dan menambahkan token yang dikembalikan olehITokenProvider
ke metadata.
Autentikasi sertifikat klien
Klien dapat menyediakan sertifikat klien untuk autentikasi. Autentikasi sertifikat terjadi di tingkat TLS, jauh sebelum ASP.NET Core. Ketika permintaan memasuki ASP.NET Core, paket autentikasi sertifikat klien memungkinkan Anda menyelesaikan sertifikat ke ClaimsPrincipal
.
Catatan
Konfigurasikan server untuk menerima sertifikat klien. Untuk informasi tentang menerima sertifikat klien di Kestrel, IIS, dan Azure, lihat Mengonfigurasi autentikasi sertifikat di ASP.NET Core.
Di klien .NET gRPC, sertifikat klien ditambahkan ke HttpClientHandler
yang kemudian digunakan untuk membuat klien gRPC:
public Ticketer.TicketerClient CreateClientWithCert(
string baseAddress,
X509Certificate2 certificate)
{
// Add client cert to the handler
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);
// Create the gRPC channel
var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
{
HttpHandler = handler
});
return new Ticketer.TicketerClient(channel);
}
Mekanisme autentikasi lainnya
Banyak mekanisme autentikasi yang didukung ASP.NET Core bekerja dengan gRPC:
- Microsoft Entra ID
- Sertifikat Klien
- IdentityServer
- JWT Token
- OAuth 2.0
- OpenID Connect
- WS-Federation
Untuk informasi selengkapnya tentang mengonfigurasi autentikasi di server, lihat autentikasi ASP.NET Core.
Mengonfigurasi klien gRPC untuk menggunakan autentikasi akan bergantung pada mekanisme autentikasi yang Anda gunakan. Contoh token pembawa dan sertifikat klien sebelumnya menunjukkan beberapa cara klien gRPC dapat dikonfigurasi untuk mengirim metadata autentikasi dengan panggilan gRPC:
- Klien gRPC yang sangat ditik menggunakan
HttpClient
secara internal. Autentikasi dapat dikonfigurasi pada HttpClientHandler, atau dengan menambahkan instans kustom HttpMessageHandler keHttpClient
. - Setiap panggilan gRPC memiliki argumen opsional
CallOptions
. Header kustom dapat dikirim menggunakan koleksi header opsi.
Catatan
Autentikasi Windows (NTLM/Kerberos/Negosiasi) tidak dapat digunakan dengan gRPC. gRPC memerlukan HTTP/2, dan HTTP/2 tidak mendukung Autentikasi Windows.
Mengotorisasi pengguna untuk mengakses layanan dan metode layanan
Secara default, semua metode dalam layanan dapat dipanggil oleh pengguna yang tidak diabaikan. Untuk memerlukan autentikasi, terapkan [Authorize]
atribut ke layanan:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}
Anda dapat menggunakan argumen konstruktor dan properti [Authorize]
atribut untuk membatasi akses hanya ke pengguna yang cocok dengan kebijakan otorisasi tertentu. Misalnya, jika Anda memiliki kebijakan otorisasi kustom yang disebut MyAuthorizationPolicy
, pastikan hanya pengguna yang cocok dengan kebijakan tersebut yang dapat mengakses layanan menggunakan kode berikut:
[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}
Metode layanan individual juga dapat [Authorize]
menerapkan atribut . Jika pengguna saat ini tidak cocok dengan kebijakan yang diterapkan ke metode dan kelas, kesalahan dikembalikan ke pemanggil:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
public override Task<AvailableTicketsResponse> GetAvailableTickets(
Empty request, ServerCallContext context)
{
// ... buy tickets for the current user ...
}
[Authorize("Administrators")]
public override Task<BuyTicketsResponse> RefundTickets(
BuyTicketsRequest request, ServerCallContext context)
{
// ... refund tickets (something only Administrators can do) ..
}
}
Sumber Daya Tambahan:
ASP.NET Core
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk