type PerRPCCredentials

传token需要实现这个接口

  1. type PerRPCCredentials interface {
  2. // GetRequestMetadata gets the current request metadata, refreshing
  3. // tokens if required. This should be called by the transport layer on
  4. // each request, and the data should be populated in headers or other
  5. // context. If a status code is returned, it will be used as the status
  6. // for the RPC. uri is the URI of the entry point for the request.
  7. // When supported by the underlying implementation, ctx can be used for
  8. // timeout and cancellation. Additionally, RequestInfo data will be
  9. // available via ctx to this call.
  10. // TODO(zhaoq): Define the set of the qualified keys instead of leaving
  11. // it as an arbitrary string.
  12. GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
  13. // RequireTransportSecurity indicates whether the credentials requires
  14. // transport security.
  15. RequireTransportSecurity() bool
  16. }

type TransportCredentials

  1. type TransportCredentials interface {
  2. // ClientHandshake does the authentication handshake specified by the
  3. // corresponding authentication protocol on rawConn for clients. It returns
  4. // the authenticated connection and the corresponding auth information
  5. // about the connection. The auth information should embed CommonAuthInfo
  6. // to return additional information about the credentials. Implementations
  7. // must use the provided context to implement timely cancellation. gRPC
  8. // will try to reconnect if the error returned is a temporary error
  9. // (io.EOF, context.DeadlineExceeded or err.Temporary() == true). If the
  10. // returned error is a wrapper error, implementations should make sure that
  11. // the error implements Temporary() to have the correct retry behaviors.
  12. // Additionally, ClientHandshakeInfo data will be available via the context
  13. // passed to this call.
  14. //
  15. // If the returned net.Conn is closed, it MUST close the net.Conn provided.
  16. ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
  17. // ServerHandshake does the authentication handshake for servers. It returns
  18. // the authenticated connection and the corresponding auth information about
  19. // the connection. The auth information should embed CommonAuthInfo to return additional information
  20. // about the credentials.
  21. //
  22. // If the returned net.Conn is closed, it MUST close the net.Conn provided.
  23. ServerHandshake(net.Conn) (net.Conn, AuthInfo, error)
  24. // Info provides the ProtocolInfo of this TransportCredentials.
  25. Info() ProtocolInfo
  26. // Clone makes a copy of this TransportCredentials.
  27. Clone() TransportCredentials
  28. // OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server.
  29. // gRPC internals also use it to override the virtual hosting name if it is set.
  30. // It must be called before dialing. Currently, this is only used by grpclb.
  31. OverrideServerName(string) error
  32. }

func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error)

  • NewClientTLSFromFile从客户机的输入证书文件构造TLS凭据。serverNameOverride仅用于测试。如果设置为非空字符串,它将覆盖请求中权限的虚拟主机名(例如:权限头字段)。

func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error)

  • NewServerTLSFromFile从服务器的输入证书文件和密钥文件构造TLS凭据

使用tls加密传输

1.安装openssl,使用openssl生成公钥与私钥

  1. 1.生成RSA私钥:openssl genrsa -out server.key 2048
  2. 命令的最后一个参数,将指定生成密钥的位数,如果没有指定,默认512
  3. 2.生成公钥 openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650
  4. openssl req:生成自签名证书,
  5. -new指生成证书请求、
  6. -sha256指使用sha256加密、
  7. -key指定私钥文件、
  8. -x509指输出证书、
  9. -days 3650为有效期
  10. 此后则输入证书拥有者信息
  11. Country Name (2 letter code) [AU]:CN
  12. State or Province Name (full name) [Some-State]:XxXx
  13. Locality Name (eg, city) []:XxXx
  14. Organization Name (eg, company) [Internet Widgits Pty Ltd]:XX Co. Ltd
  15. Organizational Unit Name (eg, section) []:Dev
  16. Common Name (e.g. server FQDN or YOUR name) []:go-grpc-example
  17. Email Address []:xxx@xxx.com

2.client端

  1. package main
  2. import (
  3. "google.golang.org/grpc"
  4. "grpcSSLCode/message"
  5. "context"
  6. "google.golang.org/grpc/grpclog"
  7. "fmt"
  8. "google.golang.org/grpc/credentials"
  9. )
  10. func main() {
  11. //TLS连接
  12. creds, err := credentials.NewClientTLSFromFile("./keys/server.pem", "go-grpc-example")
  13. if err != nil {
  14. panic(err.Error())
  15. }
  16. //1、Dail连接
  17. conn, err := grpc.Dial("localhost:8092", grpc.WithTransportCredentials(creds))
  18. if err != nil {
  19. panic(err.Error())
  20. }
  21. defer conn.Close()
  22. .....
  23. }

3.服务端

  1. package main
  2. import (
  3. "context"
  4. "grpcSSLCode/message"
  5. "fmt"
  6. "google.golang.org/grpc"
  7. "google.golang.org/grpc/credentials"
  8. "google.golang.org/grpc/grpclog"
  9. "net"
  10. )
  11. type MathManager struct {
  12. }
  13. func (mm *MathManager) AddMethod(ctx context.Context, request *message.RequestArgs) (response *message.Response, err error) {
  14. ....
  15. return response, nil
  16. }
  17. func main() {
  18. grpc.WithPerRPCCredentials()
  19. //TLS认证
  20. creds, err := credentials.NewServerTLSFromFile("./keys/server.pem", "./keys/server.key")
  21. if err != nil {
  22. grpclog.Fatal("加载在证书文件失败", err)
  23. }
  24. //实例化grpc server, 开启TLS认证
  25. server := grpc.NewServer(grpc.Creds(creds))
  26. message.RegisterMathServiceServer(server, new(MathManager))
  27. lis, err := net.Listen("tcp", ":8092")
  28. if err != nil {
  29. panic(err.Error())
  30. }
  31. server.Serve(lis)
  32. }

使用Token+tls

1.client端

  1. package main
  2. import (
  3. "google.golang.org/grpc"
  4. "gRPCTokenCode/message"
  5. "context"
  6. "google.golang.org/grpc/grpclog"
  7. "fmt"
  8. "google.golang.org/grpc/credentials"
  9. )
  10. //token认证
  11. type TokenAuthentication struct {
  12. AppKey string
  13. AppSecret string
  14. }
  15. //组织token认证的metadata信息
  16. func (ta *TokenAuthentication) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
  17. return map[string]string{
  18. "appid": ta.AppKey,
  19. "appkey": ta.AppSecret,
  20. }, nil
  21. }
  22. //是否基于TLS认证进行安全传输
  23. func (a *TokenAuthentication) RequireTransportSecurity() bool {
  24. return true
  25. }
  26. func main() {
  27. //TLS连接
  28. creds, err := credentials.NewClientTLSFromFile("./keys/server.pem", "go-grpc-example")
  29. if err != nil {
  30. panic(err.Error())
  31. }
  32. auth := TokenAuthentication{
  33. AppKey: "hello1",
  34. AppSecret: "20190812",
  35. }
  36. //1、Dail连接
  37. conn, err := grpc.Dial("localhost:8093", grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&auth))
  38. if err != nil {
  39. panic(err.Error())
  40. }
  41. defer conn.Close()
  42. ...
  43. }

2.server端

  1. package main
  2. import (
  3. "context"
  4. "gRPCTokenCode/message"
  5. "fmt"
  6. "google.golang.org/grpc"
  7. "google.golang.org/grpc/credentials"
  8. "google.golang.org/grpc/grpclog"
  9. "net"
  10. "google.golang.org/grpc/codes"
  11. "google.golang.org/grpc/status"
  12. "google.golang.org/grpc/metadata"
  13. )
  14. type MathManager struct {
  15. }
  16. func (mm *MathManager) AddMethod(ctx context.Context, request *message.RequestArgs) (response *message.Response, err error) {
  17. //通过metadata
  18. md, exist := metadata.FromIncomingContext(ctx)
  19. if !exist {
  20. return nil, status.Errorf(codes.Unauthenticated, "无Token认证信息")
  21. }
  22. var appKey string
  23. var appSecret string
  24. if key, ok := md["appid"]; ok {
  25. appKey = key[0]
  26. }
  27. if secret, ok := md["appkey"]; ok {
  28. appSecret = secret[0]
  29. }
  30. if appKey != "hello" || appSecret != "20190812" {
  31. return nil, status.Errorf(codes.Unauthenticated, "Token 不合法")
  32. }
  33. ....
  34. return response, nil
  35. }
  36. func main() {
  37. //TLS认证
  38. creds, err := credentials.NewServerTLSFromFile("./keys/server.pem", "./keys/server.key")
  39. if err != nil {
  40. grpclog.Fatal("加载在证书文件失败", err)
  41. }
  42. //实例化grpc server, 开启TLS认证
  43. server := grpc.NewServer(grpc.Creds(creds),grpc.UnaryInterceptor())
  44. message.RegisterMathServiceServer(server, new(MathManager))
  45. lis, err := net.Listen("tcp", ":8093")
  46. if err != nil {
  47. panic(err.Error())
  48. }
  49. .....
  50. server.Serve(lis)
  51. }