GRPC 中的身份验证和授权 ASP.NET Core
对调用 gRPC 服务的用户进行身份验证
gRPC 可以与ASP.NET Core authentication一起使用,以将用户与每个调用相关联。
下面是使用 gRPC 和 ASP.NET Core 身份验证的 Startup.Configure
的示例:
public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { routes.MapGrpcService<GreeterService>(); }); }
备注
注册 ASP.NET Core 身份验证中间件的顺序。 始终在 UseRouting
之后和 UseEndpoints
之前调用 UseAuthentication
和 UseAuthorization
。
需要配置应用在调用期间使用的身份验证机制。 身份验证配置是在 Startup.ConfigureServices
中添加的,会根据应用使用的身份验证机制而有所不同。 有关如何保护 ASP.NET Core 应用的示例,请参阅身份验证示例。
设置身份验证后,可以通过 ServerCallContext
在 gRPC 服务方法中访问该用户。
public override Task<BuyTicketsResponse> BuyTickets( BuyTicketsRequest request, ServerCallContext context) { var user = context.GetHttpContext().User; // ... access data from ClaimsPrincipal ... }
持有者令牌身份验证
客户端可以提供用于身份验证的访问令牌。 服务器验证令牌并使用它来标识用户。
在服务器上,持有者令牌身份验证使用 JWT 持有者中间件进行配置。
在 .NET gRPC 客户端中,可通过调用以标头的形式发送令牌:
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; }
在通道上配置 ChannelCredentials
是使用 gRPC 调用将令牌发送到服务的一种替代方法。 每次进行 gRPC 调用时,都将运行该凭据,这样就无需在多个位置编写代码即可自行传递令牌。
以下示例中的凭据将通道配置为通过每个 gRPC 调用发送令牌:
private static GrpcChannel CreateAuthenticatedChannel(string address) { var credentials = CallCredentials.FromInterceptor((context, metadata) => { if (!string.IsNullOrEmpty(_token)) { metadata.Add("Authorization", $"Bearer {_token}"); } return Task.CompletedTask; }); // SslCredentials is used here because this channel is using TLS. // CallCredentials can't be used with ChannelCredentials.Insecure on non-TLS channels. var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions { Credentials = ChannelCredentials.Create(new SslCredentials(), credentials) }); return channel; }
客户端证书身份验证
客户端还可以提供用于身份验证的客户端证书。 证书身份验证发生在 TLS 级别,在它被 ASP.NET Core 之前。 当请求输入 ASP.NET Core 时,客户端证书身份验证包可让你将证书解析为 ClaimsPrincipal
。
备注
需要将主机配置为接受客户端证书。 有关在 Kestrel、IIS 和 Azure 中接受客户端证书的信息,请参阅配置主机以要求提供证书。
在 .NET gRPC 客户端中,会将客户端证书添加到 HttpClientHandler
,然后使用该证书创建 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 { HttpClient = new HttpClient(handler) }); return new Ticketer.TicketerClient(channel); }
其他身份验证机制
许多支持 ASP.NET Core 的身份验证机制都适用于 gRPC:
- Azure Active Directory
- 客户端证书
- IdentityServer
- JWT 令牌
- OAuth 2.0
- OpenID Connect
- WS-Federation
有关在服务器上配置身份验证的详细信息,请参阅ASP.NET Core authentication。
将 gRPC 客户端配置为使用身份验证将取决于所使用的身份验证机制。 以前的持有者令牌和客户端证书示例显示了几种方法,gRPC 客户端可以配置为通过 gRPC 调用发送身份验证元数据:
- 强类型化 gRPC 客户端在内部使用
HttpClient
。 可以在HttpClientHandler上配置身份验证,或者通过将自定义HttpMessageHandler实例添加到HttpClient
。 - 每个 gRPC 调用都有一个可选
CallOptions
参数。 可以使用选项的标头集合来发送自定义标头。
备注
Windows 身份验证(NTLM/Kerberos/协商)不能与 gRPC 一起使用。 gRPC 要求使用 HTTP/2,但是 HTTP/2 不支持 Windows 身份验证。
授权用户访问服务和服务方法
默认情况下,服务中的所有方法都可以由未经身份验证的用户调用。 若要要求身份验证,请将[Authorize]
特性应用于服务:
[Authorize] public class TicketerService : Ticketer.TicketerBase { }
可以使用 [Authorize]
特性的构造函数参数和属性,将访问权限限制为仅提供给符合特定授权策略的用户。 例如,如果你有一个名为 MyAuthorizationPolicy
的自定义授权策略,请确保只有符合该策略的用户才能使用以下代码访问该服务:
[Authorize("MyAuthorizationPolicy")] public class TicketerService : Ticketer.TicketerBase { }
单个服务方法还可以应用 [Authorize]
特性。 如果当前用户与应用于方法和类的策略都不匹配,则会向调用方返回错误:
[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) .. } }