Ruby实现gRPC服务端SSL/TLS认证及自定义Token请求头的方案
解决方案
错误原因
GRPC::Core::CallCredentials的回调函数必须接收1个入参(存储当前调用的配置信息,无需使用可以用占位符_),你当前使用的无参proc会导致参数匹配错误,metadata无法正常注入请求。- 未确认服务端对请求头的大小写、认证前缀要求:部分服务对
authorization的大小写敏感,同时要确认认证前缀是否确实为Plain,大部分gRPC服务的token前缀是Bearer。 - 如果服务端使用自签SSL证书,空初始化的
ChannelCredentials无法完成TLS握手,需要传入服务端根证书。
正确实现代码
场景1:服务端使用公共可信SSL证书
# 初始化通道凭证 channel_creds = GRPC::Core::ChannelCredentials.new # 定义带参数的认证回调 auth_proc = proc do |_call_opts| { 'authorization' => 'Plain 替换为实际有效token' } end call_creds = GRPC::Core::CallCredentials.new(auth_proc) # 组合两种凭证 combined_creds = channel_creds.compose(call_creds) # 初始化Stub,注意替换为你自己的服务Stub类 @stub = YourService::Stub.new('host:port', combined_creds)
场景2:服务端使用自签SSL证书
只需要调整通道凭证初始化逻辑即可,其余代码和上面一致:
# 读取服务端根证书内容 root_cert = File.read('path/to/your/server_root_cert.pem') channel_creds = GRPC::Core::ChannelCredentials.new(root_cert)
可选:单次调用传递metadata(更灵活)
如果不需要全局绑定认证信息,也可以在每次调用RPC方法时单独传入metadata,无需配置CallCredentials:
# 初始化Stub时只传通道凭证 @stub = YourService::Stub.new('host:port', GRPC::Core::ChannelCredentials.new) # 调用时传入自定义头 response = @stub.你的RPC方法名( 请求参数对象, metadata: { 'authorization' => 'Plain 替换为实际有效token' } )
排查建议
- 先确认token的有效性,可先通过curl、postman等工具模拟调用验证权限
- 可开启gRPC调试日志确认头是否注入成功:运行程序前设置环境变量
GRPC_VERBOSITY=DEBUG GRPC_TRACE=call_opts,查看请求metadata是否包含正确的认证头 - 优先测试将认证前缀改为
Bearer,确认是否是前缀不匹配导致的权限错误
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

