0.编写.proto
1syntax = "proto3"; 2 3option java_multiple_files = true; 4option java_package = "io.grpc.examples.helloworld"; 5option java_outer_classname = "HelloWorldProto"; 6option objc_class_prefix = "HLW"; 7 8package helloworld; 9 10service Greeter { 11 rpc SayHello (HelloRequest) returns (HelloReply) {} 12} 13 14message HelloRequest { 15 string name = 1; 16} 17 18message HelloReply { 19 string message = 1; 20}
1.编译.proto生成Java源文件:
1protoc --grpc_out=..\\java --plugin=protoc-gen-grpc=D:\\Dev\\protoc\\protoc-gen-grpc-java-1.9.1-windows-x86_64.exe helloworld.proto 2protoc --java_out=..\\java helloworld.proto
2.生成CA根证书、服务器证书及客户端证书
1openssl genrsa -passout pass:111111 -des3 -out ca.key 4096 2openssl req -passin pass:111111 -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=localhost" 3openssl genrsa -passout pass:111111 -des3 -out server.key 4096 4openssl req -passin pass:111111 -new -key server.key -out server.csr -subj "/CN=localhost" 5openssl x509 -req -passin pass:111111 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt 6openssl rsa -passin pass:111111 -in server.key -out server.key 7openssl genrsa -passout pass:111111 -des3 -out client.key 4096 8openssl req -passin pass:111111 -new -key client.key -out client.csr -subj "/CN=localhost" 9openssl x509 -passin pass:111111 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt 10openssl rsa -passin pass:111111 -in client.key -out client.key 11openssl pkcs8 -topk8 -nocrypt -in client.key -out client.pem 12openssl pkcs8 -topk8 -nocrypt -in server.key -out server.pem
3.编写Server端代码
1package io.grpc.examples.helloworldtls; 2 3import io.grpc.Server; 4import io.grpc.examples.helloworld.GreeterGrpc; 5import io.grpc.examples.helloworld.HelloReply; 6import io.grpc.examples.helloworld.HelloRequest; 7import io.grpc.netty.GrpcSslContexts; 8import io.grpc.netty.NettyServerBuilder; 9import io.grpc.stub.StreamObserver; 10import io.netty.handler.ssl.ClientAuth; 11import io.netty.handler.ssl.SslContextBuilder; 12import io.netty.handler.ssl.SslProvider; 13 14import java.io.File; 15import java.io.IOException; 16import java.net.InetSocketAddress; 17import java.util.logging.Logger; 18 19public class HelloWorldServerTls { 20 private static final Logger logger = Logger.getLogger(HelloWorldServerTls.class.getName()); 21 22 private Server server; 23 24 private final String host; 25 private final int port; 26 private final String certChainFilePath; 27 private final String privateKeyFilePath; 28 private final String trustCertCollectionFilePath; 29 30 public HelloWorldServerTls(String host, 31 int port, 32 String certChainFilePath, 33 String privateKeyFilePath, 34 String trustCertCollectionFilePath) { 35 this.host = host; 36 this.port = port; 37 this.certChainFilePath = certChainFilePath; 38 this.privateKeyFilePath = privateKeyFilePath; 39 this.trustCertCollectionFilePath = trustCertCollectionFilePath; 40 } 41 42 private SslContextBuilder getSslContextBuilder() { 43 SslContextBuilder sslClientContextBuilder = SslContextBuilder.forServer(new File(certChainFilePath), 44 new File(privateKeyFilePath)); 45 if (trustCertCollectionFilePath != null) { 46 sslClientContextBuilder.trustManager(new File(trustCertCollectionFilePath)); 47 sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE); 48 } 49 return GrpcSslContexts.configure(sslClientContextBuilder, 50 SslProvider.OPENSSL); 51 } 52 53 private void start() throws IOException { 54 server = NettyServerBuilder.forAddress(new InetSocketAddress(host, port)) 55 .addService(new GreeterImpl()) 56 .sslContext(getSslContextBuilder().build()) 57 .build() 58 .start(); 59 logger.info("Server started, listening on " + port); 60 Runtime.getRuntime().addShutdownHook(new Thread() { 61 @Override 62 public void run() { 63 // Use stderr here since the logger may have been reset by its JVM shutdown hook. 64 System.err.println("*** shutting down gRPC server since JVM is shutting down"); 65 HelloWorldServerTls.this.stop(); 66 System.err.println("*** server shut down"); 67 } 68 }); 69 } 70 71 private void stop() { 72 if (server != null) { 73 server.shutdown(); 74 } 75 } 76 77 private void blockUntilShutdown() throws InterruptedException { 78 if (server != null) { 79 server.awaitTermination(); 80 } 81 } 82 83 public static void main(String[] args) throws IOException, InterruptedException { 84 85 if (args.length < 4 || args.length > 5) { 86 System.out.println( 87 "USAGE: HelloWorldServerTls host port certChainFilePath privateKeyFilePath " + 88 "[trustCertCollectionFilePath]\n Note: You only need to supply trustCertCollectionFilePath if you want " + 89 "to enable Mutual TLS."); 90 System.exit(0); 91 } 92 93 final HelloWorldServerTls server = new HelloWorldServerTls(args[0], 94 Integer.parseInt(args[1]), 95 args[2], 96 args[3], 97 args.length == 5 ? args[4] : null); 98 server.start(); 99 server.blockUntilShutdown(); 100 } 101 102 static class GreeterImpl extends GreeterGrpc.GreeterImplBase { 103 104 @Override 105 public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { 106 HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); 107 responseObserver.onNext(reply); 108 responseObserver.onCompleted(); 109 } 110 } 111}
4.编写Client端代码
1package io.grpc.examples.helloworldtls; 2 3import io.grpc.ManagedChannel; 4import io.grpc.StatusRuntimeException; 5import io.grpc.examples.helloworld.GreeterGrpc; 6import io.grpc.examples.helloworld.HelloReply; 7import io.grpc.examples.helloworld.HelloRequest; 8import io.grpc.examples.helloworld.HelloWorldServer; 9import io.grpc.netty.GrpcSslContexts; 10import io.grpc.netty.NegotiationType; 11import io.grpc.netty.NettyChannelBuilder; 12import io.netty.handler.ssl.SslContext; 13import io.netty.handler.ssl.SslContextBuilder; 14 15import javax.net.ssl.SSLException; 16import java.io.File; 17import java.util.concurrent.TimeUnit; 18import java.util.logging.Level; 19import java.util.logging.Logger; 20 21public class HelloWorldClientTls { 22 private static final Logger logger = Logger.getLogger(HelloWorldClientTls.class.getName()); 23 24 private final ManagedChannel channel; 25 private final GreeterGrpc.GreeterBlockingStub blockingStub; 26 27 private static SslContext buildSslContext(String trustCertCollectionFilePath, 28 String clientCertChainFilePath, 29 String clientPrivateKeyFilePath) throws SSLException { 30 SslContextBuilder builder = GrpcSslContexts.forClient(); 31 if (trustCertCollectionFilePath != null) { 32 builder.trustManager(new File(trustCertCollectionFilePath)); 33 } 34 if (clientCertChainFilePath != null && clientPrivateKeyFilePath != null) { 35 builder.keyManager(new File(clientCertChainFilePath), new File(clientPrivateKeyFilePath)); 36 } 37 return builder.build(); 38 } 39 40 public HelloWorldClientTls(String host, 41 int port, 42 SslContext sslContext) throws SSLException { 43 44 this(NettyChannelBuilder.forAddress(host, port) 45 .negotiationType(NegotiationType.TLS) 46 .sslContext(sslContext) 47 .build()); 48 } 49 50 HelloWorldClientTls(ManagedChannel channel) { 51 this.channel = channel; 52 blockingStub = GreeterGrpc.newBlockingStub(channel); 53 } 54 55 public void shutdown() throws InterruptedException { 56 channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); 57 } 58 59 public void greet(String name) { 60 logger.info("Will try to greet " + name + " ..."); 61 HelloRequest request = HelloRequest.newBuilder().setName(name).build(); 62 HelloReply response; 63 try { 64 response = blockingStub.sayHello(request); 65 } catch (StatusRuntimeException e) { 66 logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); 67 return; 68 } 69 logger.info("Greeting: " + response.getMessage()); 70 } 71 72 public static void main(String[] args) throws Exception { 73 if (args.length < 2 || args.length == 4 || args.length > 5) { 74 System.out.println("USAGE: HelloWorldClientTls host port [trustCertCollectionFilePath] " + 75 "[clientCertChainFilePath] [clientPrivateKeyFilePath]\n Note: clientCertChainFilePath and " + 76 "clientPrivateKeyFilePath are only needed if mutual auth is desired. And if you specify " + 77 "clientCertChainFilePath you must also specify clientPrivateKeyFilePath"); 78 System.exit(0); 79 } 80 81 { 82 HelloWorldClientTls client; 83 switch (args.length) { 84 case 2: 85 client = new HelloWorldClientTls(args[0], Integer.parseInt(args[1]), 86 buildSslContext(null, null, null)); 87 break; 88 case 3: 89 client = new HelloWorldClientTls(args[0], Integer.parseInt(args[1]), 90 buildSslContext(args[2], null, null)); 91 break; 92 default: 93 client = new HelloWorldClientTls(args[0], Integer.parseInt(args[1]), 94 buildSslContext(args[2], args[3], args[4])); 95 } 96 97 try { 98 String user = "world"; 99 if (args.length > 0) { 100 user = args[0]; /* Use the arg as the name to greet if provided */ 101 } 102 client.greet(user); 103 } finally { 104 client.shutdown(); 105 } 106 } 107 } 108}
5.分别运行Server、Client代码:
(Server端加入运行参数:localhost 50051 D:\openssl-keys\server.crt D:\openssl-keys\server.pem)
(Client端加入运行参数:localhost 50051 D:\openssl-keys\ca.crt D:\openssl-keys\client.crt D:\openssl-keys\client.pem)
运行如下:
