preface
Hello, I am fish fry. In the previous chapter, we introduced two methods of global authentication:
- TLS Certificate Authentication
- Ca-based TLS certificate authentication
- Unary and Stream interceptor
In practice, RPC methods of some modules are often authenticated or verified. Today we will explain and implement this function point
Knowledge before class
typePerRPCCredentials interface { GetRequestMetadata(ctx context.Context, uri ... string) (map[string]string, error) RequireTransportSecurity() bool }Copy the code
The PerRPCCredentials are defined by default in gRPC, which is the focus of this section. By default, gRPC provides an interface for custom authentication, which adds the required security authentication information to the context of each RPC method. It contains two methods:
- GetRequestMetadata: Obtain the metadata required for authentication of the current request.
- RequireTransportSecurity: specifies whether TLS authentication is required for secure transmission
The directory structure
Go and simple_token_client/client.go. The directory structure is as follows:
├─ │ ├─ Simple_http_├ ─ Simple_token_client │ ├─ Simple_token_client │ ├─ Simple_token_client │ ├─ ├ ─ ─ the conf ├ ─ ─ PKG ├ ─ ─ proto ├ ─ ─ server │ ├ ─ ─ simple_http_server │ ├ ─ ─ simple_server │ ├ ─ ─ simple_token_server │ └ ─ ─ Stream_server └ ─ ─ vendorCopy the code
gRPC
Client
package main
import (
"context"
"log"
"google.golang.org/grpc"
"github.com/EDDYCJY/go-grpc-example/pkg/gtls"
pb "github.com/EDDYCJY/go-grpc-example/proto"
)
const PORT = "9004"
typeAuth struct { AppKey string AppSecret string } func (a *Auth) GetRequestMetadata(ctx context.Context, uri ... string) (map[string]string, error) {return map[string]string{"app_key": a.AppKey, "app_secret": a.AppSecret}, nil
}
func (a *Auth) RequireTransportSecurity() bool {
return true
}
func main() {
tlsClient := gtls.Client{
ServerName: "go-grpc-example",
CertFile: ".. /.. /conf/server/server.pem",
}
c, err := tlsClient.GetTLSCredentials()
iferr ! = nil { log.Fatalf("tlsClient.GetTLSCredentials err: %v", err)
}
auth := Auth{
AppKey: "eddycjy",
AppSecret: "20181005",
}
conn, err := grpc.Dial(":"+PORT, grpc.WithTransportCredentials(c), grpc.WithPerRPCCredentials(&auth))
...
}
Copy the code
On the Client side, implement the methods required by the Type PerRPCCredentials Interface. Note the following:
- Struct Auth: GetRequestMetadata, RequireTransportSecurity
- grpc.WithPerRPCCredentials
Server
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"github.com/EDDYCJY/go-grpc-example/pkg/gtls"
pb "github.com/EDDYCJY/go-grpc-example/proto"
)
type SearchService struct {
auth *Auth
}
func (s *SearchService) Search(ctx context.Context, r *pb.SearchRequest) (*pb.SearchResponse, error) {
iferr := s.auth.Check(ctx); err ! = nil {return nil, err
}
return &pb.SearchResponse{Response: r.GetRequest() + " Token Server"}, nil
}
const PORT = "9004"
func main() {... }type Auth struct {
appKey string
appSecret string
}
func (a *Auth) Check(ctx context.Context) error {
md, ok := metadata.FromIncomingContext(ctx)
if! ok {return status.Errorf(codes.Unauthenticated, "Failed to customize authentication Token")
}
var (
appKey string
appSecret string
)
if value, ok := md["app_key"]; ok {
appKey = value[0]
}
if value, ok := md["app_secret"]; ok {
appSecret = value[0]
}
ifappKey ! = a.GetAppKey() || appSecret ! = a.GetAppSecret() {
return status.Errorf(codes.Unauthenticated, "Invalid custom authentication Token")}return nil
}
func (a *Auth) GetAppKey() string {
return "eddycjy"
}
func (a *Auth) GetAppSecret() string {
return "20181005"
}
Copy the code
On the Server side is more simple, the actual is called metadata. FromIncomingContext get the metadata from the context, then authentication checks in the different methods of RPC
validation
Restart server.go and client.go with the following results:
$ go run client.go
2018/10/05 20:59:58 resp: gRPC Token Server
Copy the code
Error: Client. go (); error: client.go ();
$ go run client.go
2018/10/05 21:00:05 client.Search err: rpc error: code = Unauthenticated desc = invalid token
exit status 1
Copy the code
Adding them one by one is too much trouble
I’m sure you’ll ask each one. Isn’t it too much trouble? You should make the Type PerRPCCredentials Interface an interceptor.
conclusion
This section is relatively simple, mainly for RPC method custom authentication is introduced, if you want to do global, the suggestion is to start from interceptor oh.
?
If you have any questions or mistakes, welcome to raise questions or give correction opinions on issues. If you like or are helpful to you, welcome Star, which is a kind of encouragement and promotion for the author.
My official account
reference
Sample code for this series
- go-grpc-example