You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中实现gRPC基础认证(Basic Authentication)?

在C#中实现gRPC基本认证(Basic Authentication)

服务端实现

gRPC服务端通过**拦截器(Interceptor)**处理认证逻辑,拦截所有入站请求并验证Basic Auth凭证:

1. 实现认证拦截器

using Grpc.Core;
using Grpc.Core.Interceptors;
using System.Text;

public class BasicAuthServerInterceptor : ServerInterceptor
{
    private readonly Func<string, string, bool> _validateCredentials;

    // 注入自定义校验逻辑,替换硬编码的凭证验证
    public BasicAuthServerInterceptor(Func<string, string, bool> validateCredentials)
    {
        _validateCredentials = validateCredentials;
    }

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        if (!IsValidCredential(context))
        {
            throw new RpcException(new Status(StatusCode.Unauthenticated, "无效或缺失的Basic认证凭证"));
        }

        return await continuation(request, context);
    }

    // 按需实现流式请求的拦截逻辑
    public override async Task ServerStreamingServerHandler<TRequest, TResponse>(
        TRequest request,
        IServerStreamWriter<TResponse> responseStream,
        ServerCallContext context,
        ServerStreamingServerMethod<TRequest, TResponse> continuation)
    {
        if (!IsValidCredential(context))
        {
            throw new RpcException(new Status(StatusCode.Unauthenticated, "无效或缺失的Basic认证凭证"));
        }

        await continuation(request, responseStream, context);
    }

    private bool IsValidCredential(ServerCallContext context)
    {
        if (!context.RequestHeaders.TryGetValue("Authorization", out var authHeader))
        {
            return false;
        }

        var authValue = authHeader.Value;
        if (!authValue.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        // 解码Base64格式的凭证
        var encodedCredentials = authValue["Basic ".Length..];
        var credentialBytes = Convert.FromBase64String(encodedCredentials);
        var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':', 2);

        if (credentials.Length != 2)
        {
            return false;
        }

        return _validateCredentials(credentials[0], credentials[1]);
    }
}

2. 注册拦截器到gRPC服务

启动服务时添加拦截器,传入实际的用户校验逻辑(比如查询数据库):

using Grpc.Core;

// 自定义用户校验逻辑示例
bool ValidateUser(string username, string password)
{
    // 替换为你的实际验证逻辑,比如查询数据库
    return username == "admin" && password == "secure123";
}

var server = new Server
{
    Services = { Greeter.BindService(new GreeterServiceImpl()) },
    Ports = { new ServerPort("localhost", 50051, ServerCredentials.Insecure) }
};

// 添加Basic Auth拦截器
server.Interceptors.Add(new BasicAuthServerInterceptor(ValidateUser));

server.Start();
Console.WriteLine("gRPC服务运行在端口50051");
Console.ReadLine();
await server.ShutdownAsync();

客户端实现

客户端通过拦截器在每次请求中自动添加Basic Auth头:

1. 实现客户端拦截器

using Grpc.Core;
using Grpc.Core.Interceptors;
using System.Text;

public class BasicAuthClientInterceptor : Interceptor
{
    private readonly string _authHeaderValue;

    public BasicAuthClientInterceptor(string username, string password)
    {
        // 预编码凭证,避免每次请求重复计算
        var credentials = $"{username}:{password}";
        var encodedCredentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
        _authHeaderValue = $"Basic {encodedCredentials}";
    }

    public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
        TRequest request,
        ClientInterceptorContext<TRequest, TResponse> context,
        AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
    {
        var updatedOptions = context.Options.WithHeaders(new Metadata
        {
            { "Authorization", _authHeaderValue }
        });

        return continuation(request, new ClientInterceptorContext<TRequest, TResponse>(context.Method, context.Host, updatedOptions));
    }

    // 按需实现流式请求的拦截逻辑
    public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(
        TRequest request,
        ClientInterceptorContext<TRequest, TResponse> context,
        AsyncServerStreamingCallContinuation<TRequest, TResponse> continuation)
    {
        var updatedOptions = context.Options.WithHeaders(new Metadata
        {
            { "Authorization", _authHeaderValue }
        });

        return continuation(request, new ClientInterceptorContext<TRequest, TResponse>(context.Method, context.Host, updatedOptions));
    }
}

2. 创建带拦截器的客户端

using Grpc.Net.Client;

// 创建gRPC通道
var channel = GrpcChannel.ForAddress("http://localhost:50051");

// 添加Basic Auth拦截器到客户端
var greeterClient = new Greeter.GreeterClient(channel.Intercept(new BasicAuthClientInterceptor("admin", "secure123")));

// 发起请求
var reply = await greeterClient.SayHelloAsync(new HelloRequest { Name = "World" });
Console.WriteLine("响应: " + reply.Message);

生产环境注意事项

  • 必须使用HTTPS传输,避免凭证明文泄露,服务端配置ServerCredentials.Ssl,客户端使用https://地址。
  • 不要硬编码凭证,建议从配置文件或密钥管理服务读取。
  • 可扩展拦截器支持更多gRPC调用类型(客户端流式、双向流式)。

内容的提问来源于stack exchange,提问作者Brian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:40:31