Commit 563acaf72e78686be3aeac31069439365896a141

Authored by zhangqijia
1 parent f7f4beb5

在拦截器中认证jwt

actions/accountaction.go
... ... @@ -9,40 +9,33 @@ import (
9 9 "pro2d/utils"
10 10 )
11 11  
12   -func (s *AccountServer) RegisterHandler(ctx context.Context, in *pb.Register) (*pb.PubRsp, error) {
  12 +func (s *LoginServer) RegisterHandler(ctx context.Context, in *pb.Register) (*pb.RegisterRsp, error) {
13 13 ok, account := models.AccountExistByPhone(in.Phone)
14 14 if !ok {
15 15 account.Phone = in.Phone
16 16 account.Password = utils.Md5V(in.Password)
17 17 account.Uid = conf.SnowFlack.NextValStr()
18   - account.Device = "123123"
19 18 account.Create()
20 19 }else {
21 20 return nil, fmt.Errorf("1")
22 21 }
23 22  
24   - return &pb.PubRsp{
  23 + return &pb.RegisterRsp{
25 24 Code: 0,
26 25 }, nil
27 26 }
28 27  
29   -func (s *AccountServer) CreateTokenHandler(ctx context.Context, in *pb.AccountInfo) (*pb.CreateTokenRsp, error) {
  28 +func (s *LoginServer) CreateTokenHandler(ctx context.Context, in *pb.Account) (*pb.CreateTokenRsp, error) {
30 29 m := models.NewAccount(in.Phone)
31 30 if err := m.Load(); err != nil {
32 31 return &pb.CreateTokenRsp{
33   - Rsp: &pb.PubRsp{
34   - Code: 1,
35   - Msg: err.Error(),
36   - },
  32 + Code: 1,
37 33 }, nil
38 34 }
39 35  
40 36 if m.Password != utils.Md5V(in.Password) {
41 37 return &pb.CreateTokenRsp{
42   - Rsp: &pb.PubRsp{
43   - Code: 2,
44   - Msg: "password error",
45   - },
  38 + Code: 2,
46 39 }, nil
47 40 }
48 41  
... ... @@ -57,10 +50,9 @@ func (s *AccountServer) CreateTokenHandler(ctx context.Context, in *pb.AccountIn
57 50 }
58 51  
59 52 return &pb.CreateTokenRsp{
60   - Rsp: &pb.PubRsp{
61   - Code: 0,
62   - },
63   - Token: utils.CreateToken(m.AccountInfo),
  53 + Code: 0,
  54 + Uid: m.Uid,
  55 + Token: utils.CreateToken(m.Account),
64 56 GameService: gameInfo,
65 57 }, nil
66 58 }
... ...
actions/roleaction.go
... ... @@ -3,85 +3,50 @@ package actions
3 3 import (
4 4 "context"
5 5 "errors"
6   - "fmt"
7 6 "google.golang.org/grpc/metadata"
  7 + "google.golang.org/protobuf/types/known/emptypb"
8 8 "pro2d/conf"
9 9 "pro2d/models"
10 10 "pro2d/protos/pb"
11 11 "pro2d/utils"
12 12 )
13 13  
14   -func (s *GameServer) HeartBeatHandler(ctx context.Context, in *pb.Token) (*pb.PubRsp, error) {
  14 +func (s *GameServer) HeartBeatHandler(ctx context.Context, empty *emptypb.Empty) (*pb.HeartRsp, error) {
15 15 utils.Sugar.Debugf("HeartBeatHandler被调用!!!")
16 16 //获取元数据信息
17   - md,ok := metadata.FromIncomingContext(ctx)
  17 + _,ok := metadata.FromIncomingContext(ctx)
18 18 if !ok {
19 19 return nil,errors.New("未传输token")
20 20 }
21   - var (
22   - appId string
23   - appKey string
24   - )
25   - if val, ok := md["appId"]; ok {
26   - appId = val[0]
27   - }
28   - if val, ok := md["appKey"]; ok {
29   - appKey = val[0]
30   - }
31   - //进行校验的信息是否正确
32   - if appId != "123" || appKey != "456" {
33   - return nil, errors.New("token传输不正确")
34   - }
35 21  
36   - return &pb.PubRsp{
  22 + return &pb.HeartRsp{
37 23 Code: 0,
38   - Msg: "heart beat successful",
39 24 }, nil
40 25 }
41 26  
42   -func (s *GameServer) CreateRoleHandler(ctx context.Context, in *pb.Token) (*pb.RoleRsp, error) {
43   - account := utils.ParseToken(in.Token)
44   - if account == nil {
45   - return nil, fmt.Errorf("1")
46   - }
47   - ok, role := models.RoleExistByUid(account.Uid)
  27 +func (s *GameServer) CreateRoleHandler(ctx context.Context, in *pb.LoginReq) (*pb.RoleRsp, error) {
  28 + ok, role := models.RoleExistByUid(in.Uid)
48 29 if !ok {
49 30 role = models.NewRole(conf.SnowFlack.NextVal())
50   - role.Role.Device = account.Device
51   - role.Role.Uid = account.Uid
  31 + role.Role.Device = in.Device
  32 + role.Role.Uid = in.Uid
52 33 role.Create()
53   -
54 34 }
55 35 return &pb.RoleRsp{
56   - Rsp: &pb.PubRsp{
57   - Code: 0,
58   - Msg: "successful",
59   - },
  36 + Code: 0,
60 37 Role: role.Role,
61 38 }, nil
62 39 }
63 40  
64   -func (s *GameServer) LoginHandler(ctx context.Context, in *pb.Token) (*pb.RoleRsp, error) {
65   - account := utils.ParseToken(in.Token)
66   - if account == nil {
67   - return nil, fmt.Errorf("token is error")
68   - }
69   - utils.Sugar.Debugf("login account: %v", account)
70   - ok, role := models.RoleExistByUid(account.Uid)
  41 +func (s *GameServer) LoginHandler(ctx context.Context, in *pb.LoginReq) (*pb.RoleRsp, error) {
  42 + ok, role := models.RoleExistByUid(in.Uid)
71 43 if !ok {
72 44 return &pb.RoleRsp{
73   - Rsp: &pb.PubRsp{
74   - Code: 1,
75   - Msg: "role not exist",
76   - },
77   -
  45 + Code: 1,
78 46 }, nil
79 47 }
80 48 return &pb.RoleRsp{
81   - Rsp: &pb.PubRsp{
82   - Code: 0,
83   - Msg: "successful",
84   - },
  49 + Code: 0,
85 50 Role: role.Role,
86 51 Hero: models.GetHeros(role.Heros),
87 52 }, nil
... ...
actions/server.go
... ... @@ -2,6 +2,7 @@ package actions
2 2  
3 3 import (
4 4 "context"
  5 + "fmt"
5 6 "google.golang.org/grpc"
6 7 "google.golang.org/grpc/reflection"
7 8 "pro2d/conf"
... ... @@ -10,13 +11,13 @@ import (
10 11 "pro2d/utils"
11 12 )
12 13  
13   -type AccountServer struct{
14   - pb.UnimplementedAccountServer
  14 +type LoginServer struct{
  15 + pb.UnsafeLoginServer
15 16 *BasicServer
16 17 }
17 18  
18   -func NewAccountServer() *AccountServer {
19   - return &AccountServer{
  19 +func NewAccountServer() *LoginServer {
  20 + return &LoginServer{
20 21 BasicServer: NewServer(),
21 22 }
22 23 }
... ... @@ -30,7 +31,7 @@ func AccountServerInterceptor(ctx context.Context, req interface{}, info *grpc.U
30 31 return resp, err
31 32 }
32 33  
33   -func (s *AccountServer)Start() error {
  34 +func (s *LoginServer)Start() error {
34 35 lis, err := s.BasicServer.Start(conf.GlobalConf.AccountConf)
35 36 if err != nil {
36 37 return err
... ... @@ -41,17 +42,17 @@ func (s *AccountServer)Start() error {
41 42 //new一个grpc
42 43 s.GrpcServer = grpc.NewServer(grpc.UnaryInterceptor(AccountServerInterceptor))
43 44  
44   - pb.RegisterAccountServer(s.GrpcServer, s)
  45 + pb.RegisterLoginServer(s.GrpcServer, s)
45 46 reflection.Register(s.GrpcServer) //在给定的gRPC服务器上注册服务器反射服务
46 47  
47 48 // Serve方法在lis上接受传入连接,为每个连接创建一个ServerTransport和server的goroutine。
48 49 // 该goroutine读取gRPC请求,然后调用已注册的处理程序来响应它们。
49   - utils.Sugar.Debugf("Start AccountServer listening on %d", conf.GlobalConf.AccountConf.Port)
  50 + utils.Sugar.Debugf("Start LoginServer listening on %d", conf.GlobalConf.AccountConf.Port)
50 51  
51 52 return s.GrpcServer.Serve(lis)
52 53 }
53 54  
54   -func (s *AccountServer)Stop() {
  55 +func (s *LoginServer)Stop() {
55 56 s.BasicServer.Stop()
56 57 }
57 58  
... ... @@ -69,7 +70,12 @@ func NewGameServer() *GameServer {
69 70 func GameServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
70 71 handler grpc.UnaryHandler) (interface{}, error) {
71 72  
72   - utils.Sugar.Debugf("gRPC method: %s, %v", info.FullMethod, req)
  73 + //utils.Sugar.Debugf("gRPC method: %s, %v", info.FullMethod, req)
  74 + acc := utils.CheckAuth(ctx)
  75 + if acc == nil {
  76 + return nil, fmt.Errorf("token error")
  77 + }
  78 +
73 79 resp, err := handler(ctx, req)
74 80 return resp, err
75 81 }
... ...
... ... @@ -5,6 +5,7 @@ go 1.17
5 5 require (
6 6 github.com/dgrijalva/jwt-go v3.2.0+incompatible
7 7 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
  8 + go.etcd.io/etcd/api/v3 v3.5.2
8 9 go.etcd.io/etcd/client/v3 v3.5.2
9 10 go.mongodb.org/mongo-driver v1.8.3
10 11 go.uber.org/zap v1.17.0
... ... @@ -27,7 +28,6 @@ require (
27 28 github.com/xdg-go/scram v1.0.2 // indirect
28 29 github.com/xdg-go/stringprep v1.0.2 // indirect
29 30 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
30   - go.etcd.io/etcd/api/v3 v3.5.2 // indirect
31 31 go.etcd.io/etcd/client/pkg/v3 v3.5.2 // indirect
32 32 go.uber.org/atomic v1.7.0 // indirect
33 33 go.uber.org/multierr v1.6.0 // indirect
... ...
models/account.go
... ... @@ -7,7 +7,7 @@ import (
7 7  
8 8 type AccountModel struct {
9 9 *db.MgoColl
10   - *pb.AccountInfo
  10 + *pb.Account
11 11 }
12 12  
13 13 func AccountExistByPhone(phone string) (bool, *AccountModel){
... ... @@ -19,12 +19,12 @@ func AccountExistByPhone(phone string) (bool, *AccountModel){
19 19 }
20 20  
21 21 func NewAccount(phone string) *AccountModel {
22   - ac := &pb.AccountInfo{
  22 + ac := &pb.Account{
23 23 Phone: phone,
24 24 }
25 25 account := &AccountModel{
26 26 MgoColl: db.NewMongoColl(phone, ac),
27   - AccountInfo: ac,
  27 + Account: ac,
28 28 }
29 29  
30 30 return account
... ...
models/init.go
... ... @@ -24,7 +24,7 @@ func InitDoc(schema ...interface{}) {
24 24  
25 25 func InitAccountServerModels() {
26 26 var schema []interface{} = []interface{}{
27   - pb.AccountInfo{},
  27 + pb.Account{},
28 28 }
29 29 InitDoc(schema...)
30 30 }
... ...
test/client.go
... ... @@ -9,7 +9,7 @@ import (
9 9 "pro2d/utils"
10 10 )
11 11  
12   -func Register(c pb.AccountClient, phone, password string) error {
  12 +func Register(c pb.LoginClient, phone, password string) error {
13 13 r, err := c.RegisterHandler(context.Background(), &pb.Register{
14 14 Phone: "17683852936",
15 15 Password: "123456",
... ... @@ -20,14 +20,17 @@ func Register(c pb.AccountClient, phone, password string) error {
20 20 return err
21 21 }
22 22 if r.Code != 0 {
23   - return fmt.Errorf("%s", r.Msg)
  23 + return fmt.Errorf("register fail")
24 24 }
25 25 utils.Sugar.Debug("register success")
26 26 return nil
27 27 }
28 28  
29   -func Login(loginUri, token string) {
30   - gameConn, err := grpc.Dial(loginUri, grpc.WithInsecure() )
  29 +func Login(loginUri, token, uid string) {
  30 + var opts []grpc.DialOption
  31 + // 指定自定义认证
  32 + opts = append(opts, grpc.WithPerRPCCredentials(&utils.AuthToken{Token: token}), grpc.WithInsecure())
  33 + gameConn, err := grpc.Dial(loginUri, opts...)
31 34 if err != nil {
32 35 utils.Sugar.Errorf("game conn err: %v", err)
33 36 return
... ... @@ -36,8 +39,9 @@ func Login(loginUri, token string) {
36 39  
37 40 client:= pb.NewGameClient(gameConn)
38 41 var role *pb.Role
39   - loginRsp, err := client.LoginHandler(context.Background(), &pb.Token{
40   - Token: token,
  42 + loginRsp, err := client.LoginHandler(context.Background(), &pb.LoginReq{
  43 + Uid: uid,
  44 + Device: "111111",
41 45 })
42 46  
43 47 if err != nil {
... ... @@ -46,14 +50,14 @@ func Login(loginUri, token string) {
46 50 }
47 51 role = loginRsp.Role
48 52  
49   - if loginRsp.Rsp.Code != 0 {
50   - utils.Sugar.Debugf("login rsp: %v", loginRsp.Rsp.Msg)
51   - createRole, err := client.CreateRoleHandler(context.Background(), &pb.Token{Token: token})
  53 + if loginRsp.Code != 0 {
  54 + utils.Sugar.Debugf("login fail, role not exist")
  55 + createRole, err := client.CreateRoleHandler(context.Background(), &pb.LoginReq{Uid: uid, Device: "11111"})
52 56 if err != nil {
53 57 utils.Sugar.Errorf("create role err: %v", err)
54 58 return
55 59 }
56   - utils.Sugar.Debug("create role rsp: ", createRole.Rsp.Code, createRole.Rsp.Msg)
  60 + utils.Sugar.Debug("create role rsp: ", createRole.Code)
57 61 role = createRole.Role
58 62 }
59 63  
... ... @@ -67,13 +71,13 @@ func main() {
67 71 return
68 72 }
69 73 defer conn.Close()
70   - c := pb.NewAccountClient(conn)
71   - //err = Register(c,"17683852936", "123456")
  74 + c := pb.NewLoginClient(conn)
  75 + err = Register(c,"17683852936", "123456")
72 76 //if err != nil {
73 77 // utils.Sugar.Errorf("register err: %v", err)
74 78 // return
75 79 //}
76   - rsp, err := c.CreateTokenHandler(context.Background(), &pb.AccountInfo{
  80 + rsp, err := c.CreateTokenHandler(context.Background(), &pb.Account{
77 81 Phone: "17683852936",
78 82 Password: "123456",
79 83 })
... ... @@ -83,12 +87,12 @@ func main() {
83 87 return
84 88 }
85 89  
86   - if rsp.Rsp.Code != 0 {
87   - utils.Sugar.Errorf("createtoken err: %v", rsp.Rsp.Msg)
  90 + if rsp.Code != 0 {
  91 + utils.Sugar.Errorf("createtoken err" )
88 92 return
89 93 }
90 94  
91 95 if len(rsp.GameService) >0 {
92   - Login(rsp.GameService[0].Address, rsp.Token)
  96 + Login(rsp.GameService[0].Address, rsp.Token, rsp.Uid)
93 97 }
94 98 }
... ...
utils/jwt.go
... ... @@ -10,7 +10,7 @@ import (
10 10 "google.golang.org/grpc/metadata"
11 11 )
12 12  
13   -func CreateToken(account *pb.AccountInfo) (tokenString string) {
  13 +func CreateToken(account *pb.Account) (tokenString string) {
14 14 token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
15 15 "iss": "pro2d-app-server",
16 16 "aud": "pro2d-app-server",
... ... @@ -19,7 +19,6 @@ func CreateToken(account *pb.AccountInfo) (tokenString string) {
19 19 "sub": "pro2d",
20 20 "phone": account.Phone,
21 21 "uid": account.Uid,
22   - "device": account.Device,
23 22 })
24 23 tokenString, err := token.SignedString([]byte(Pro2DTokenSignedString))
25 24 if err != nil {
... ... @@ -28,7 +27,7 @@ func CreateToken(account *pb.AccountInfo) (tokenString string) {
28 27 return tokenString
29 28 }
30 29  
31   -func ParseToken(tokenStr string)*pb.AccountInfo {
  30 +func ParseToken(tokenStr string)*pb.Account{
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" {
... ... @@ -47,23 +46,9 @@ func ParseToken(tokenStr string)*pb.AccountInfo {
47 46 Sugar.Error("ErrInvalidToken")
48 47 return nil
49 48 }
50   - return &clientClaims.AccountInfo
  49 + return &clientClaims.Account
51 50 }
52 51  
53   -// AuthToken 自定义认证
54   -type AuthToken struct {
55   - Token string
56   -}
57   -
58   -func (c AuthToken) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
59   - return map[string]string{
60   - "authorization": c.Token,
61   - }, nil
62   -}
63   -
64   -func (c AuthToken) RequireTransportSecurity() bool {
65   - return false
66   -}
67 52  
68 53 // Claims defines the struct containing the token claims.
69 54 type Claims struct {
... ... @@ -71,7 +56,7 @@ type Claims struct {
71 56 //phone string `json:"phone"`
72 57 //uid int64 `json:"uid"`
73 58 //device string `json:"device"`
74   - pb.AccountInfo
  59 + pb.Account
75 60 }
76 61  
77 62 // 从 context 的 metadata 中,取出 token
... ... @@ -89,10 +74,26 @@ func getTokenFromContext(ctx context.Context) (string, error) {
89 74 return token[0], nil
90 75 }
91 76  
92   -func CheckAuth(ctx context.Context) *pb.AccountInfo {
  77 +func CheckAuth(ctx context.Context) *pb.Account{
93 78 tokenStr, err := getTokenFromContext(ctx)
94 79 if err != nil {
95   - panic("get token from context error")
  80 + Sugar.Errorf("get token from context error")
  81 + return nil
96 82 }
97 83 return ParseToken(tokenStr)
  84 +}
  85 +
  86 +// AuthToken 自定义认证 客户端使用
  87 +type AuthToken struct {
  88 + Token string
  89 +}
  90 +
  91 +func (c AuthToken) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
  92 + return map[string]string{
  93 + "authorization": c.Token,
  94 + }, nil
  95 +}
  96 +
  97 +func (c AuthToken) RequireTransportSecurity() bool {
  98 + return false
98 99 }
99 100 \ No newline at end of file
... ...
utils/jwt_test.go
... ... @@ -7,11 +7,10 @@ import (
7 7 )
8 8  
9 9 func TestCreateToken(t *testing.T) {
10   - account := &pb.AccountInfo{
  10 + account := &pb.Account{
11 11 Phone: "17683852936",
12 12 Password: "123456",
13   - Uid: 12312,
14   - Device: "12312312",
  13 + Uid: "12312",
15 14 }
16 15 token := CreateToken(account)
17 16 ac := ParseToken(token)
... ...