gRPC使用SSL连接

使用OpenSSL生成密钥

本文以《gRPC基本使用的C++示例工程》文章中的示例MFC工程为基础,添加SSL相关代码。

例如在工程生成目录(D:\SoftwareDevelopment\gRPC_Study\gRPC_Example\x64\Debug)下创建ssl文件夹,然后生成有效期365天的密钥。

1、安装OpenSSL

可以在官网下载、源码编译,本文使用vcpkg进行安装。

vcpkg install openssl

2、设置环境变量

  • Path里添加openssl的安装路径,例如:D:\SoftwareDevelopment\vcpkg\installed\x64-windows\tools\openssl
  • 添加用户变量OPENSSL_CONF,设置值为openssl文件夹的openssl.cnf文件路径,例如:D:\SoftwareDevelopment\vcpkg\installed\x64-windows\tools\openssl\openssl.cn

3、生成key和证书

openssl genrsa -out D:\SoftwareDevelopment\gRPC_Study\gRPC_Example\x64\Debug\ssl\server.key 2048
openssl req -new -x509 -days 365 -subj "/C=CN/L=Beijing/O=mengmei/CN=localhost" -key D:\SoftwareDevelopment\gRPC_Study\gRPC_Example\x64\Debug\ssl\server.key -out D:\SoftwareDevelopment\gRPC_Study\gRPC_Example\x64\Debug\ssl\server.crt
openssl genrsa -out D:\SoftwareDevelopment\gRPC_Study\gRPC_Example\x64\Debug\ssl\client.key 2048
openssl req -new -x509 -days 365 -subj "/C=CN/L=Shanghai/O=mengmei/CN=localhost" -key D:\SoftwareDevelopment\gRPC_Study\gRPC_Example\x64\Debug\ssl\client.key -out D:\SoftwareDevelopment\gRPC_Study\gRPC_Example\x64\Debug\ssl\client.crt

subj参数说明

字段字段含义示例
/C=Country 国家CN
/ST=State or Province 省Beijing
/L=Location or City 城市Shanghai
/O=Organization 组织或企业mengmei
/OU=Organization Unit 部门dev
/CN=Common Name 域名或IPlocalhost

服务端关键代码

	_builder = make_unique<ServerBuilder>();
	// _builder->AddListeningPort(serverAddr, grpc::InsecureServerCredentials());// 监听不需要认证的连接

	auto GetFileString = [&](string extraFilePath)
	{
		char buf[MAX_PATH] = { 0 };
		GetModuleFileNameA(NULL, buf, MAX_PATH * sizeof(char));
		GetLongPathNameA(buf, buf, MAX_PATH * sizeof(char));
		PathRemoveFileSpecA(buf);
		PathAppendA(buf, extraFilePath.c_str());

		ifstream in(buf);
		istreambuf_iterator<char> beg(in), end;
		string str(beg, end);
		return str;
	};

	// 增加SSL验证
	grpc::SslServerCredentialsOptions sslOpts{};
	sslOpts.client_certificate_request = GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;
	sslOpts.pem_key_cert_pairs.push_back(grpc::SslServerCredentialsOptions::PemKeyCertPair{ GetFileString("ssl/server.key"), GetFileString("ssl/server.crt") });
	sslOpts.pem_root_certs = GetFileString("ssl/client.crt");
	auto creds = grpc::SslServerCredentials(sslOpts);
	_builder->AddListeningPort(serverAddr, creds);

客户端关键代码

	auto GetFileString = [&](string extraFilePath)
	{
		char buf[MAX_PATH] = { 0 };
		GetModuleFileNameA(NULL, buf, MAX_PATH * sizeof(char));
		GetLongPathNameA(buf, buf, MAX_PATH * sizeof(char));
		PathRemoveFileSpecA(buf);
		PathAppendA(buf, extraFilePath.c_str());

		ifstream in(buf);
		istreambuf_iterator<char> beg(in), end;
		string str(beg, end);
		return str;
	};

	// 创建gRPC channel
	// _channel = grpc::CreateChannel(serverAddr, grpc::InsecureChannelCredentials()); // 监听不需要认证的连接
	// 增加SSL验证
	grpc::SslCredentialsOptions sslOpts;
	sslOpts.pem_root_certs = GetFileString("ssl/server.crt");
	sslOpts.pem_private_key = GetFileString("ssl/client.key");
	sslOpts.pem_cert_chain = GetFileString("ssl/client.crt");
	auto creds = grpc::SslCredentials(sslOpts);
	_channel = grpc::CreateChannel(serverAddr, creds);

	_stub = UserService::NewStub(_channel);

参考文章

  1. 《GRPC的SSL安全实现》作者:
  2. 《使用OpenSSL生成自签名SSL证书》作者:

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注