ASP.NET Core 7中gRPC服务的认证授权实现方案咨询
在ASP.NET Core 7中实现gRPC服务的JWT认证授权
一、核心思路
无需手动维护令牌-用户ID字典,直接依托ASP.NET Core的JWT认证中间件,结合gRPC的上下文/拦截器完成认证,同时在业务方法中安全获取用户标识(如客户端ID)来筛选数据。
二、第一步:配置ASP.NET Core的JWT认证
在Program.cs中配置JWT认证服务与gRPC托管:
var builder = WebApplication.CreateBuilder(args); // 注册JWT认证 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; // 适配gRPC的Authorization头部传递逻辑 options.Events = new JwtBearerEvents { OnMessageReceived = context => { var token = context.Request.Headers.Authorization.FirstOrDefault()?.Split(" ").Last(); if (!string.IsNullOrEmpty(token)) { context.Token = token; } return Task.CompletedTask; } }; }); builder.Services.AddAuthorization(); // 注册gRPC服务 builder.Services.AddGrpc(); var app = builder.Build(); // 启用认证、授权中间件 app.UseAuthentication(); app.UseAuthorization(); // 映射gRPC服务 app.MapGrpcService<MyBankService>(); app.MapGrpcService<AuthService>(); app.Run();
三、第二步:实现登录接口生成JWT令牌
创建专门的gRPC认证服务,验证用户凭证后生成包含客户端ID的JWT返回给客户端,无需手动维护令牌映射:
public class AuthService : AuthServiceBase // 对应gRPC定义的Auth服务契约 { private readonly IConfiguration _config; private readonly IClientRepository _clientRepository; public AuthService(IConfiguration config, IClientRepository clientRepository) { _config = config; _clientRepository = clientRepository; } public override async Task<LoginResponse> Login(LoginRequest request, ServerCallContext context) { // 验证用户名与密码 var client = await _clientRepository.GetClient(request.Username); if (client == null || !BCrypt.Net.BCrypt.Verify(request.Password, client.HashedPassword)) { throw new RpcException(new Status(StatusCode.Unauthenticated, "用户名或密码错误")); } // 生成嵌入客户端ID的JWT令牌 var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var claims = new[] { new Claim(ClaimTypes.NameIdentifier, client.Id.ToString()), new Claim(ClaimTypes.Name, client.Username) }; var token = new JwtSecurityToken( issuer: _config["Jwt:Issuer"], audience: _config["Jwt:Audience"], claims: claims, expires: DateTime.Now.AddMinutes(30), signingCredentials: credentials); return new LoginResponse { Token = new JwtSecurityTokenHandler().WriteToken(token) }; } }
四、第三步:在gRPC业务服务中获取客户端ID
直接从ServerCallContext的HTTP上下文里提取已认证用户的Claim信息,无需手动处理令牌验证:
public class MyBankService : BankServiceBase // 对应gRPC定义的Bank服务契约 { private readonly IApplicationService _applicationService; public MyBankService(IApplicationService applicationService) { _applicationService = applicationService; } public override async Task<BankAccountResponse> GetBankAccountOfClient(EmptyRequest request, ServerCallContext context) { // 从认证上下文提取客户端ID var clientIdClaim = context.GetHttpContext().User.FindFirst(ClaimTypes.NameIdentifier); if (clientIdClaim == null || !long.TryParse(clientIdClaim.Value, out long clientId)) { throw new RpcException(new Status(StatusCode.Unauthenticated, "未获取到有效用户信息")); } // 调用应用层获取用户专属数据 var account = await _applicationService.GetBankAccountOfClient(clientId); // 仅返回非敏感数据 return new BankAccountResponse { AccountId = account.Id, Balance = account.Balance, AccountType = account.Type.ToString() }; } }
五、可选:用gRPC拦截器统一处理认证校验
如果需要对所有gRPC方法统一做认证/权限检查,可实现拦截器:
public class AuthInterceptor : Interceptor { private readonly IAuthorizationService _authorizationService; public AuthInterceptor(IAuthorizationService authorizationService) { _authorizationService = authorizationService; } public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>( TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation) { // 检查用户是否已认证 if (!context.GetHttpContext().User.Identity.IsAuthenticated) { throw new RpcException(new Status(StatusCode.Unauthenticated, "用户未完成认证")); } // 可选:检查用户是否具备指定权限 var authResult = await _authorizationService.AuthorizeAsync(context.GetHttpContext().User, null, "BankAccessPolicy"); if (!authResult.Succeeded) { throw new RpcException(new Status(StatusCode.PermissionDenied, "无访问权限")); } return await continuation(request, context); } }
在Program.cs中注册拦截器:
builder.Services.AddGrpc(options => { options.Interceptors.Add<AuthInterceptor>(); });
方案优势
- 无需手动维护令牌字典:JWT自身包含用户标识与过期信息,由ASP.NET Core自动验证有效性,过期后自动失效
- 安全可控:JWT签名机制确保令牌无法篡改,认证逻辑与业务逻辑解耦
- 符合架构分层:ASP.NET Core负责认证校验,gRPC服务专注业务实现,避免敏感数据泄露
内容的提问来源于stack exchange,提问作者Álvaro García
相关产品推荐
相关产品推荐

