双向认证下rpc-gateway使用(同时提供rpc和http服务)

下载go get -v github.com/grpc-ecosystem/grpc-gateway,然后把这个包下面的third-party下面的google文件夹拷贝到Prod.proto的同级目录下

syntax = "proto3";
package services;
import "google/api/annotations.proto"; //引入proto

message ProdRequest {
    int32 prod_id = 1; //传入id
}

message ProdResponse {
    int32 prod_stock = 1; //商品库存
}


service ProdService {
    rpc GetProdStock (ProdRequest) returns (ProdResponse) {
        option (google.api.http) = {
            get: "/v1/prod/{prod_id}" //和request中的prod_id对应,不能写错
        };
    }
}

然后重新生成pb文件和生成pb.gw.go网关文件

封装服务端证书配置和客户端证书配置文件

package helper

import (
    "crypto/tls"
    "crypto/x509"
    "google.golang.org/grpc/credentials"
    "io/ioutil"
)

//获取服务端证书配置
func GetServerCreds() credentials.TransportCredentials  {
    cert,_:=tls.LoadX509KeyPair("cert/server.pem","cert/server.key")
    certPool := x509.NewCertPool()
    ca, _ := ioutil.ReadFile("cert/ca.pem")
    certPool.AppendCertsFromPEM(ca)

    creds:=credentials.NewTLS(&tls.Config{
        Certificates: []tls.Certificate{cert},//服务端证书
        ClientAuth:   tls.VerifyClientCertIfGiven,
        ClientCAs:    certPool,
    })
    return creds
}
//获取客户端证书配置
func  GetClientCreds() credentials.TransportCredentials   {
    cert,_:=tls.LoadX509KeyPair("cert/client.pem","cert/client.key")
    certPool := x509.NewCertPool()
    ca, _ := ioutil.ReadFile("cert/ca.pem")
    certPool.AppendCertsFromPEM(ca)

    creds:=credentials.NewTLS(&tls.Config{
        Certificates: []tls.Certificate{cert},//客户端证书
        ServerName: "localhost",
        RootCAs:      certPool,
    })
    return creds
}

编写HttpServer文件,由于是http访问grpc,所以http也相当于一个客户端,需要提供客户端秘钥才可以成功访问

package main

import (
    "context"
    "github.com/grpc-ecosystem/grpc-gateway/runtime"
    "google.golang.org/grpc"
    "grpcpro/helper"
    "grpcpro/services"
    "log"
    "net/http"
)

func main() {
    gwmux := runtime.NewServeMux()
    opt := []grpc.DialOption{grpc.WithTransportCredentials(helper.GetClientCreds())}                           //由于是http访问grpc,所以http也相当于一个客户端,需要提供客户端秘钥才可以成功访问
    err := services.RegisterProdServiceHandlerFromEndpoint(context.Background(), gwmux, "localhost:8081", opt) //localhost这是grpc的地址
    if err != nil {
        log.Fatal(err)
    }
    httpServer := &http.Server{
        Addr:    ":8080",
        Handler: gwmux,
    }
    httpServer.ListenAndServe()
}

grpc server文件

package main

import (
    "google.golang.org/grpc"
    "grpcpro/helper"
    "grpcpro/services"
    "net"
)

func main() {

    //creds, err := credentials.NewServerTLSFromFile("keys/server.crt",
    //    "keys/server.key")
    //if err != nil {
    //    log.Fatal(err)
    //}
    creds := helper.GetServerCreds() //这里这个方法取到的是服务端证书配置
    rpcServer := grpc.NewServer(grpc.Creds(creds))
    services.RegisterProdServiceServer(rpcServer, new(services.ProdService))

    lis, _ := net.Listen("tcp", ":8081")
    rpcServer.Serve(lis)

    //mux:=http.NewServeMux()
    //mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
    //     rpcServer.ServeHTTP(writer,request)
    //})
    //httpServer:=&http.Server{
    //    Addr:":8081",
    //    Handler:mux,
    //}
    //httpServer.ListenAndServeTLS("keys/server.crt","keys/server.key")

}




原文地址:https://www.cnblogs.com/hualou/p/12070292.html