8、更换protoc
package main
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"io/ioutil"
"log"
"net"
"zjtd.com/myproto/service"
)
func main() {
////添加单向证书
//creds, err2 := credentials.NewServerTLSFromFile("cert/server.pem", "cert/server.key")
//if err2 != nil {
// log.Fatal("证书生成错误", err2)
//}
//添加双向证书
cert, err := tls.LoadX509KeyPair("cert/server.pem", "cert/server.key")
if err != nil {
log.Fatal("证书读取错误", err)
}
// 创建一个新的、空的 CertPool
certPool := x509.NewCertPool()
ca, err := ioutil.ReadFile("cert/ca.crt")
if err != nil {
log.Fatal("ca证书读取错误", err)
}
// 尝试解析所传入的 PEM 编码的证书。如果解析成功会将其加到 CertPool 中,便于后面的使用
certPool.AppendCertsFromPEM(ca)
// 构建基于 TLS 的 TransportCredentials 选项
creds := credentials.NewTLS(&tls.Config{
// 设置证书链,允许包含一个或多个
Certificates: []tls.Certificate{cert},
// 要求必须校验客户端的证书。可以根据实际情况选用以下参数
ClientAuth: tls.RequireAndVerifyClientCert,
// 设置根证书的集合,校验方式使用 ClientAuth 中设定的模式
ClientCAs: certPool,
})
//实现token认证,需要合法的用户名和密码
//实现一个拦截器
var AuthInterceptor grpc.UnaryServerInterceptor
AuthInterceptor = func(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler) (resp interface{}, err error) {
//拦截普通方法请求,验证tokrn
err = Auth(ctx)
if err != nil {
return
}
return handler(ctx, req)
}
recServer := grpc.NewServer(grpc.Creds(creds), grpc.UnaryInterceptor(AuthInterceptor))
//new一个服务端
//recServer := grpc.NewServer(grpc.Creds(creds))
//service 是我们自己的包,里面有一个RegisterProServiceServer的方法注册一个服务
//接口实现service.ProductService被注册上了
// service.RegisterProServiceServer(服务端, 实现主体函数的任意实例 interface{})
service.RegisterProServiceServer(recServer, service.ProductService)
fmt.Println("认证成功")
listener, err := net.Listen("tcp", ":8008")
if err != nil {
log.Fatalln("启动监听失败", err)
}
err = recServer.Serve(listener)
if err != nil {
log.Fatalln("启动服务失败", err)
}
fmt.Println("启动gRPC服务成功")
}
func Auth(ctx context.Context) error {
//实际上拿到传输的用户名和密码
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return fmt.Errorf("missing credentials")
}
var user string
var password string
if val, ok := md["user.proto"]; ok {
user = val[0]
}
if val, ok := md["password"]; ok {
password = val[0]
}
if user != "hyh" || password != "123456" {
return status.Error(codes.Unauthenticated, "token不合法")
}
return nil
}