ASP.NET gRPC 服务的核心 MVC 过滤器模拟
ASP.NET Core MVC filter analogue for gRPC service
我在 ASP.NET Core 3.0 上有一个现有的 REST API 运行。它使用 MVC 过滤器根据 header 值和 returns 错误执行授权检查,以防授权失败,这样请求就不会传递给控制器。
现在,我正在试验 gRPC 并尝试将此 API 移植到 gRPC 服务。但是,我没有看到任何明显的解决方案可以作为 MVC 过滤器的替代品。
是否有某种方法可以实现类似的授权检查功能,也许使用 metadata?
这将有略微不同的答案,具体取决于您是否使用 Grpc.Core, which is a wrapper around the C GRPC library initially developed at Google, which has been available for a while and supports a variety of .Net targets (including Framework), or if you're using the new Grpc.AspNetCore,它随 .Net Core 3.0 一起启动并构建在 Kestrel 和 ASP.NET 核心内部。
Grpc.Core
对于 Grpc.Core,您可能希望将 header 值作为元数据传递,然后创建一个 server-side Interceptor to handle the metadata and the request. You can also consider using the AsyncAuthInterceptor,但是客户端的核心 Grpc 实现不会发送凭据不安全的(non-TLS)连接。
Grpc.AspNetCore
Grpc.AspNetCore 建立在 ASP.NET 和 can use ASP.NET middleware 之上,包括默认的 ASP.NET 身份验证。如果可以将过滤器转换为中间件,则可以在两个实现之间共享身份验证。
对于 MVC 和 gRpc,它们是不同的。 gRpc 下不存在 ActionFilter。
如果您想为所有操作应用检查请求 header,您可以尝试在 app.UseEndpoints
之前实现您的自定义中间件并检查请求 header。
换一种方式,您可以尝试 Policy
如下所示:
GrpcRequireemnt
和 GrpcHandler
public class GrpcRequireemnt : IAuthorizationRequirement
{
}
public class GrpcHandler : AuthorizationHandler<GrpcRequireemnt>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GrpcHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GrpcRequireemnt requirement)
{
var headers = _httpContextAccessor.HttpContext.Request.Headers;
StringValues token;
if (!headers.TryGetValue("token", out token))
{
context.Fail();
return Task.CompletedTask;
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
注册所需服务
services.AddAuthorization(options =>
{
options.AddPolicy("TokenAuthorize", policy =>
{
policy.AddRequirements(new GrpcRequireemnt());
});
});
services.AddHttpContextAccessor();
services.AddSingleton<IAuthorizationHandler, GrpcHandler>();
用例
[Authorize("TokenAuthorize")]
public override Task<BuyTicketsResponse> BuyTickets(BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
return Task.FromResult(new BuyTicketsResponse
{
Success = _ticketRepository.BuyTickets(user.Identity.Name!, request.Count)
});
}
我在 ASP.NET Core 3.0 上有一个现有的 REST API 运行。它使用 MVC 过滤器根据 header 值和 returns 错误执行授权检查,以防授权失败,这样请求就不会传递给控制器。
现在,我正在试验 gRPC 并尝试将此 API 移植到 gRPC 服务。但是,我没有看到任何明显的解决方案可以作为 MVC 过滤器的替代品。
是否有某种方法可以实现类似的授权检查功能,也许使用 metadata?
这将有略微不同的答案,具体取决于您是否使用 Grpc.Core, which is a wrapper around the C GRPC library initially developed at Google, which has been available for a while and supports a variety of .Net targets (including Framework), or if you're using the new Grpc.AspNetCore,它随 .Net Core 3.0 一起启动并构建在 Kestrel 和 ASP.NET 核心内部。
Grpc.Core
对于 Grpc.Core,您可能希望将 header 值作为元数据传递,然后创建一个 server-side Interceptor to handle the metadata and the request. You can also consider using the AsyncAuthInterceptor,但是客户端的核心 Grpc 实现不会发送凭据不安全的(non-TLS)连接。
Grpc.AspNetCore
Grpc.AspNetCore 建立在 ASP.NET 和 can use ASP.NET middleware 之上,包括默认的 ASP.NET 身份验证。如果可以将过滤器转换为中间件,则可以在两个实现之间共享身份验证。
对于 MVC 和 gRpc,它们是不同的。 gRpc 下不存在 ActionFilter。
如果您想为所有操作应用检查请求 header,您可以尝试在 app.UseEndpoints
之前实现您的自定义中间件并检查请求 header。
换一种方式,您可以尝试 Policy
如下所示:
GrpcRequireemnt
和GrpcHandler
public class GrpcRequireemnt : IAuthorizationRequirement { } public class GrpcHandler : AuthorizationHandler<GrpcRequireemnt> { private readonly IHttpContextAccessor _httpContextAccessor; public GrpcHandler(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GrpcRequireemnt requirement) { var headers = _httpContextAccessor.HttpContext.Request.Headers; StringValues token; if (!headers.TryGetValue("token", out token)) { context.Fail(); return Task.CompletedTask; } context.Succeed(requirement); return Task.CompletedTask; } }
注册所需服务
services.AddAuthorization(options => { options.AddPolicy("TokenAuthorize", policy => { policy.AddRequirements(new GrpcRequireemnt()); }); }); services.AddHttpContextAccessor(); services.AddSingleton<IAuthorizationHandler, GrpcHandler>();
用例
[Authorize("TokenAuthorize")] public override Task<BuyTicketsResponse> BuyTickets(BuyTicketsRequest request, ServerCallContext context) { var user = context.GetHttpContext().User; return Task.FromResult(new BuyTicketsResponse { Success = _ticketRepository.BuyTickets(user.Identity.Name!, request.Count) }); }