我有一个在 ASP.NET Core 3.0 上运行的现有 REST API。它使用 MVC 过滤器根据标头值执行授权检查,并在授权失败时返回错误,以便请求不会传递到控制器。
现在,我正在尝试 gRPC 并尝试将此 API 移植到 gRPC 服务。但是,我没有看到任何明显的解决方案可以替代 MVC 过滤器。
是否有某种方法可以实现类似的授权检查功能,也许使用元数据?
对于MVC和gRpc来说,它们是不同的。 gRpc 下不存在 ActionFilter。
如果您想对所有操作应用检查请求标头,您可以尝试在
app.UseEndpoints
之前实现自定义中间件并检查请求标头。
对于另一种方式,您可以尝试
Policy
,如下所示:
GrpcRequireemnt
和 GrpcHandler
public class GrpcRequirement : IAuthorizationRequirement
{
}
public class GrpcHandler : AuthorizationHandler<GrpcRequirement>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GrpcHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GrpcRequirement 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 GrpcRequirement());
});
});
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)
});
}
这将有稍微不同的答案,具体取决于您是否使用 Grpc.Core,它是最初在 Google 开发的 C GRPC 库的包装器,它已经可用了一段时间并支持各种 .Net 目标(包括 Framework),或者如果您使用的是新的 Grpc.AspNetCore,它随 .Net Core 3.0 一起启动,并且基于 Kestrel 和 ASP.NET Core 内部构建。
对于 Grpc.Core,您需要将标头值作为元数据传递,然后创建一个 服务器端拦截器 来处理元数据和请求。您还可以考虑使用 AsyncAuthInterceptor,但是客户端的核心 Grpc 实现不会通过不安全(非 TLS)连接发送凭据。
Grpc.AspNetCore 构建于 ASP.NET 之上,可以使用 ASP.NET 中间件,包括默认的 ASP.NET 身份验证。如果您可以将过滤器转换为中间件,您将能够在两个实现之间共享身份验证。