Commit 1b1ad555363e65b30856648c32b5185c52237236
1 parent
66502d8d
tls测试代码
Showing
10 changed files
with
122 additions
and
45 deletions
 
Show diff stats
actions/accountaction.go
| ... | ... | @@ -3,6 +3,7 @@ package actions | 
| 3 | 3 | import ( | 
| 4 | 4 | "context" | 
| 5 | 5 | "fmt" | 
| 6 | + "pro2d/components/jwt" | |
| 6 | 7 | "pro2d/conf" | 
| 7 | 8 | "pro2d/models" | 
| 8 | 9 | "pro2d/protos/pb" | 
| ... | ... | @@ -52,7 +53,7 @@ func (s *LoginServer) CreateTokenHandler(ctx context.Context, in *pb.Account) (* | 
| 52 | 53 | return &pb.CreateTokenRsp{ | 
| 53 | 54 | Code: 0, | 
| 54 | 55 | Uid: m.Uid, | 
| 55 | - Token: utils.CreateToken(m.Account), | |
| 56 | + Token: jwt.CreateToken(m.Account.Uid), | |
| 56 | 57 | GameService: gameInfo, | 
| 57 | 58 | }, nil | 
| 58 | 59 | } | ... | ... | 
actions/roleaction.go
| ... | ... | @@ -3,7 +3,6 @@ package actions | 
| 3 | 3 | import ( | 
| 4 | 4 | "context" | 
| 5 | 5 | "errors" | 
| 6 | - "fmt" | |
| 7 | 6 | "google.golang.org/grpc/metadata" | 
| 8 | 7 | "google.golang.org/protobuf/types/known/emptypb" | 
| 9 | 8 | "pro2d/conf" | 
| ... | ... | @@ -26,16 +25,12 @@ func (s *GameServer) HeartBeatHandler(ctx context.Context, empty *emptypb.Empty) | 
| 26 | 25 | } | 
| 27 | 26 | |
| 28 | 27 | func (s *GameServer) CreateRoleHandler(ctx context.Context, in *pb.LoginReq) (*pb.RoleRsp, error) { | 
| 29 | - account := utils.CheckAuth(ctx) | |
| 30 | - if account == nil { | |
| 31 | - return nil, fmt.Errorf("token error") | |
| 32 | - } | |
| 33 | - | |
| 34 | - ok, role := models.RoleExistByUid(account.Uid) | |
| 28 | + uid := ctx.Value("uid").(string) | |
| 29 | + ok, role := models.RoleExistByUid(uid) | |
| 35 | 30 | if !ok { | 
| 36 | 31 | role = models.NewRole(conf.SnowFlack.NextVal()) | 
| 37 | 32 | role.Role.Device = in.Device | 
| 38 | - role.Role.Uid = account.Uid | |
| 33 | + role.Role.Uid = uid | |
| 39 | 34 | role.Create() | 
| 40 | 35 | } | 
| 41 | 36 | return &pb.RoleRsp{ | 
| ... | ... | @@ -45,12 +40,8 @@ func (s *GameServer) CreateRoleHandler(ctx context.Context, in *pb.LoginReq) (* | 
| 45 | 40 | } | 
| 46 | 41 | |
| 47 | 42 | func (s *GameServer) LoginHandler(ctx context.Context, in *pb.LoginReq) (*pb.RoleRsp, error) { | 
| 48 | - account := utils.CheckAuth(ctx) | |
| 49 | - if account == nil { | |
| 50 | - return nil, fmt.Errorf("token error") | |
| 51 | - } | |
| 52 | - | |
| 53 | - ok, role := models.RoleExistByUid(account.Uid) | |
| 43 | + uid := ctx.Value("uid").(string) | |
| 44 | + ok, role := models.RoleExistByUid(uid) | |
| 54 | 45 | if !ok { | 
| 55 | 46 | return &pb.RoleRsp{ | 
| 56 | 47 | Code: 1, | ... | ... | 
actions/server.go
| ... | ... | @@ -2,9 +2,11 @@ package actions | 
| 2 | 2 | |
| 3 | 3 | import ( | 
| 4 | 4 | "context" | 
| 5 | + "fmt" | |
| 5 | 6 | "google.golang.org/grpc" | 
| 6 | 7 | "google.golang.org/grpc/credentials" | 
| 7 | 8 | "google.golang.org/grpc/reflection" | 
| 9 | + "pro2d/components/jwt" | |
| 8 | 10 | "pro2d/conf" | 
| 9 | 11 | "pro2d/models" | 
| 10 | 12 | "pro2d/protos/pb" | 
| ... | ... | @@ -86,7 +88,11 @@ func GameServerInterceptor(ctx context.Context, req interface{}, info *grpc.Unar | 
| 86 | 88 | handler grpc.UnaryHandler) (interface{}, error) { | 
| 87 | 89 | |
| 88 | 90 | //utils.Sugar.Debugf("gRPC method: %s, %v", info.FullMethod, req) | 
| 89 | - | |
| 91 | + uid := jwt.CheckAuth(ctx) | |
| 92 | + if uid == ""{ | |
| 93 | + return nil, fmt.Errorf("token error") | |
| 94 | + } | |
| 95 | + context.WithValue(ctx, "uid", uid) | |
| 90 | 96 | resp, err := handler(ctx, req) | 
| 91 | 97 | return resp, err | 
| 92 | 98 | } | ... | ... | 
utils/jwt.go renamed to components/jwt/jwt.go
| 1 | -package utils | |
| 1 | +package jwt | |
| 2 | 2 | |
| 3 | 3 | import ( | 
| 4 | 4 | "context" | 
| 5 | 5 | "fmt" | 
| 6 | 6 | "pro2d/conf" | 
| 7 | - "pro2d/protos/pb" | |
| 7 | + "pro2d/utils" | |
| 8 | 8 | "time" | 
| 9 | 9 | |
| 10 | 10 | jwt "github.com/dgrijalva/jwt-go" | 
| 11 | 11 | "google.golang.org/grpc/metadata" | 
| 12 | 12 | ) | 
| 13 | 13 | |
| 14 | -func CreateToken(account *pb.Account) (tokenString string) { | |
| 14 | +func CreateToken(uid string) (tokenString string) { | |
| 15 | 15 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | 
| 16 | 16 | "iss": "pro2d-app-server", | 
| 17 | 17 | "aud": "pro2d-app-server", | 
| 18 | 18 | "nbf": time.Now().Unix(), | 
| 19 | 19 | "exp": time.Now().Add(time.Hour).Unix(), | 
| 20 | 20 | "sub": "pro2d", | 
| 21 | - "phone": account.Phone, | |
| 22 | - "uid": account.Uid, | |
| 21 | + "uid": uid, | |
| 23 | 22 | }) | 
| 24 | - tokenString, err := token.SignedString([]byte(Pro2DTokenSignedString)) | |
| 23 | + tokenString, err := token.SignedString([]byte(utils.Pro2DTokenSignedString)) | |
| 25 | 24 | if err != nil { | 
| 26 | 25 | panic(err) | 
| 27 | 26 | } | 
| 28 | 27 | return tokenString | 
| 29 | 28 | } | 
| 30 | 29 | |
| 31 | -func ParseToken(tokenStr string)*pb.Account{ | |
| 30 | +func ParseToken(tokenStr string) string { | |
| 32 | 31 | var clientClaims Claims | 
| 33 | 32 | token, err := jwt.ParseWithClaims(tokenStr, &clientClaims, func(token *jwt.Token) (interface{}, error) { | 
| 34 | 33 | if token.Header["alg"] != "HS256" { | 
| 35 | 34 | //panic("ErrInvalidAlgorithm") | 
| 36 | - Sugar.Error("ErrInvalidAlgorithm") | |
| 35 | + utils.Sugar.Error("ErrInvalidAlgorithm") | |
| 37 | 36 | return nil, nil | 
| 38 | 37 | } | 
| 39 | - return []byte(Pro2DTokenSignedString), nil | |
| 38 | + return []byte(utils.Pro2DTokenSignedString), nil | |
| 40 | 39 | }) | 
| 41 | 40 | if err != nil { | 
| 42 | - Sugar.Error("jwt parse error") | |
| 43 | - return nil | |
| 41 | + utils.Sugar.Error("jwt parse error") | |
| 42 | + return "" | |
| 44 | 43 | } | 
| 45 | 44 | |
| 46 | 45 | if !token.Valid { | 
| 47 | - Sugar.Error("ErrInvalidToken") | |
| 48 | - return nil | |
| 46 | + utils.Sugar.Error("ErrInvalidToken") | |
| 47 | + return "" | |
| 49 | 48 | } | 
| 50 | - return &clientClaims.Account | |
| 49 | + return clientClaims.Uid | |
| 51 | 50 | } | 
| 52 | 51 | |
| 53 | 52 | |
| 54 | 53 | // Claims defines the struct containing the token claims. | 
| 55 | 54 | type Claims struct { | 
| 56 | 55 | jwt.StandardClaims | 
| 57 | - //phone string `json:"phone"` | |
| 58 | - //uid int64 `json:"uid"` | |
| 59 | - //device string `json:"device"` | |
| 60 | - pb.Account | |
| 56 | + Uid string | |
| 61 | 57 | } | 
| 62 | 58 | |
| 63 | 59 | // 从 context 的 metadata 中,取出 token | 
| ... | ... | @@ -75,11 +71,11 @@ func getTokenFromContext(ctx context.Context) (string, error) { | 
| 75 | 71 | return token[0], nil | 
| 76 | 72 | } | 
| 77 | 73 | |
| 78 | -func CheckAuth(ctx context.Context) *pb.Account{ | |
| 74 | +func CheckAuth(ctx context.Context) string { | |
| 79 | 75 | tokenStr, err := getTokenFromContext(ctx) | 
| 80 | 76 | if err != nil { | 
| 81 | - Sugar.Errorf("get token from context error") | |
| 82 | - return nil | |
| 77 | + utils.Sugar.Errorf("get token from context error") | |
| 78 | + return "" | |
| 83 | 79 | } | 
| 84 | 80 | return ParseToken(tokenStr) | 
| 85 | 81 | } | ... | ... | 
utils/jwt_test.go renamed to components/jwt/jwt_test.go
| 1 | -package utils | |
| 1 | +package jwt | |
| 2 | 2 | |
| 3 | 3 | import ( | 
| 4 | 4 | "fmt" | 
| ... | ... | @@ -12,7 +12,7 @@ func TestCreateToken(t *testing.T) { | 
| 12 | 12 | Password: "123456", | 
| 13 | 13 | Uid: "12312", | 
| 14 | 14 | } | 
| 15 | - token := CreateToken(account) | |
| 15 | + token := CreateToken(account.Uid) | |
| 16 | 16 | ac := ParseToken(token) | 
| 17 | 17 | fmt.Println("token: ", token, "\nac: ", ac) | 
| 18 | 18 | } | ... | ... | 
conf/conf.yaml
test/client.go
| ... | ... | @@ -7,6 +7,7 @@ import ( | 
| 7 | 7 | "fmt" | 
| 8 | 8 | "google.golang.org/grpc" | 
| 9 | 9 | "google.golang.org/grpc/credentials" | 
| 10 | + "pro2d/components/jwt" | |
| 10 | 11 | _ "pro2d/conf" | 
| 11 | 12 | "pro2d/protos/pb" | 
| 12 | 13 | "pro2d/utils" | 
| ... | ... | @@ -32,7 +33,7 @@ func Register(c pb.LoginClient, phone, password string) error { | 
| 32 | 33 | func Login(loginUri, token, uid string) { | 
| 33 | 34 | var opts []grpc.DialOption | 
| 34 | 35 | // 指定自定义认证 | 
| 35 | - opts = append(opts, grpc.WithPerRPCCredentials(&utils.AuthToken{Token: token})) | |
| 36 | + opts = append(opts, grpc.WithPerRPCCredentials(&jwt.AuthToken{Token: token})) | |
| 36 | 37 | if TLS { | 
| 37 | 38 | // TLS连接 | 
| 38 | 39 | creds, err := credentials.NewClientTLSFromFile("keys/server.pem", ServerName) | ... | ... | 
test/tlsclient.go
| ... | ... | @@ -4,9 +4,27 @@ import ( | 
| 4 | 4 | "context" | 
| 5 | 5 | "google.golang.org/grpc" | 
| 6 | 6 | "google.golang.org/grpc/credentials" | 
| 7 | + "google.golang.org/protobuf/types/known/emptypb" | |
| 7 | 8 | "log" | 
| 9 | + "pro2d/components/jwt" | |
| 10 | + _ "pro2d/conf" | |
| 8 | 11 | "pro2d/protos/pb" | 
| 12 | + "pro2d/utils" | |
| 9 | 13 | ) | 
| 14 | +// AuthToken 自定义认证 客户端使用 | |
| 15 | +type CustomToken struct { | |
| 16 | +} | |
| 17 | + | |
| 18 | +func (c CustomToken) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { | |
| 19 | + return map[string]string{ | |
| 20 | + "appId": "100", | |
| 21 | + "appKey": "token", | |
| 22 | + }, nil | |
| 23 | +} | |
| 24 | + | |
| 25 | +func (c CustomToken) RequireTransportSecurity() bool { | |
| 26 | + return true | |
| 27 | +} | |
| 10 | 28 | |
| 11 | 29 | func main() { | 
| 12 | 30 | var opts []grpc.DialOption | 
| ... | ... | @@ -19,7 +37,25 @@ func main() { | 
| 19 | 37 | conn, err := grpc.Dial("localhost:8948", opts...) | 
| 20 | 38 | |
| 21 | 39 | helloClient := pb.NewHelloClient(conn) | 
| 22 | - rsp, err := helloClient.SayHello(context.TODO(), &pb.HelloWorld{Msg: "hello world"}) | |
| 40 | + token, err := helloClient.CreateToken(context.TODO(), &pb.Login{ | |
| 41 | + Login: "login", | |
| 42 | + Password: "123456", | |
| 43 | + }) | |
| 44 | + if err != nil { | |
| 45 | + log.Fatal(err) | |
| 46 | + return | |
| 47 | + } | |
| 48 | + utils.Sugar.Debugf("token: %s", token.Token) | |
| 49 | + | |
| 50 | + opts = append(opts, grpc.WithPerRPCCredentials(&jwt.AuthToken{Token: token.Token})) | |
| 51 | + conn2, err := grpc.Dial("localhost:8948",opts...) | |
| 52 | + if err != nil { | |
| 53 | + log.Fatal(err) | |
| 54 | + return | |
| 55 | + } | |
| 56 | + | |
| 57 | + helloClient2 := pb.NewHelloClient(conn2) | |
| 58 | + rsp, err := helloClient2.SayHello(context.TODO(), &emptypb.Empty{}) | |
| 23 | 59 | if err != nil { | 
| 24 | 60 | log.Fatal(err) | 
| 25 | 61 | } | ... | ... | 
test/tlsserver.go
| ... | ... | @@ -2,10 +2,16 @@ package main | 
| 2 | 2 | |
| 3 | 3 | import ( | 
| 4 | 4 | "context" | 
| 5 | + "fmt" | |
| 5 | 6 | "google.golang.org/grpc" | 
| 7 | + "google.golang.org/grpc/codes" | |
| 6 | 8 | "google.golang.org/grpc/credentials" | 
| 9 | + "google.golang.org/grpc/metadata" | |
| 10 | + "google.golang.org/grpc/status" | |
| 11 | + "google.golang.org/protobuf/types/known/emptypb" | |
| 7 | 12 | "log" | 
| 8 | 13 | "net" | 
| 14 | + "pro2d/components/jwt" | |
| 9 | 15 | "pro2d/protos/pb" | 
| 10 | 16 | ) | 
| 11 | 17 | |
| ... | ... | @@ -13,10 +19,50 @@ type Server struct { | 
| 13 | 19 | pb.UnimplementedHelloServer | 
| 14 | 20 | } | 
| 15 | 21 | |
| 16 | -func (s *Server) SayHello(ctx context.Context, in *pb.HelloWorld) (*pb.HelloWorld, error) { | |
| 17 | - return in, nil | |
| 22 | +func (s *Server) CreateToken(ctx context.Context, in *pb.Login) (*pb.TokenInfo, error) { | |
| 23 | + if in.Login == "login" && in.Password == "123456" { | |
| 24 | + return &pb.TokenInfo{Token: jwt.CreateToken(in.Login)}, nil | |
| 25 | + } | |
| 26 | + return nil, fmt.Errorf("login error") | |
| 18 | 27 | } | 
| 19 | 28 | |
| 29 | +//func (s *Server) SayHello(ctx context.Context, empty *emptypb.Empty) (*pb.HelloWorld, error) { | |
| 30 | +// md, ok := metadata.FromIncomingContext(ctx) | |
| 31 | +// if !ok { | |
| 32 | +// return nil, status.Errorf(codes.Unauthenticated,"ErrNoMetadataInContext") | |
| 33 | +// } | |
| 34 | +// // md 的类型是 type MD map[string][]string | |
| 35 | +// token, ok := md["authorization"] | |
| 36 | +// if !ok || len(token) == 0 { | |
| 37 | +// return nil, status.Errorf(codes.Unauthenticated,"ErrNoAuthorizationInMetadata") | |
| 38 | +// } | |
| 39 | +// login := jwt.ParseToken(token[0]) | |
| 40 | +// return &pb.HelloWorld{Msg: "Hello world: " + login}, nil | |
| 41 | +//} | |
| 42 | + | |
| 43 | +func (s *Server) SayHello(ctx context.Context, empty *emptypb.Empty) (*pb.HelloWorld, error) { | |
| 44 | + md, ok := metadata.FromIncomingContext(ctx) | |
| 45 | + if !ok { | |
| 46 | + return nil, status.Errorf(codes.Unauthenticated, "无Token认证信息") | |
| 47 | + } | |
| 48 | + var ( | |
| 49 | + appId string | |
| 50 | + appKey string | |
| 51 | + ) | |
| 52 | + if val, ok := md["appid"]; ok { | |
| 53 | + appId = val[0] | |
| 54 | + } | |
| 55 | + | |
| 56 | + if val, ok := md["appkey"]; ok { | |
| 57 | + appKey = val[0] | |
| 58 | + } | |
| 59 | + | |
| 60 | + if appId != "100" || appKey != "token" { | |
| 61 | + return nil, status.Errorf(codes.Unauthenticated, "Token认证信息无效: appid=%s, appkey=%s", appId, appKey) | |
| 62 | + } | |
| 63 | + | |
| 64 | + return &pb.HelloWorld{Msg: "Hello world"}, nil | |
| 65 | +} | |
| 20 | 66 | func main() { | 
| 21 | 67 | // 监听本地端口 | 
| 22 | 68 | listener, err := net.Listen("tcp", ":8948") | ... | ... |