package http_handler import ( "context" "fmt" "git.hlsq.asia/mmorpg/service-common/db/redis" "git.hlsq.asia/mmorpg/service-common/log" "git.hlsq.asia/mmorpg/service-common/net/grpc/grpc_client" "git.hlsq.asia/mmorpg/service-common/net/http/http_resp" "git.hlsq.asia/mmorpg/service-common/proto/rs/grpc_pb" "git.hlsq.asia/mmorpg/service-common/utils" "git.hlsq.asia/mmorpg/service-gateway/config" "git.hlsq.asia/mmorpg/service-gateway/internal/global" "github.com/gin-gonic/gin" "time" ) // 这个模块处理用户登录 type LoginReq struct { Phone string `json:"phone"` // 手机号 Code string `json:"code"` // 验证码 WxMiniCode string `json:"wxMiniCode"` // 微信小程序登录 } type LoginResp struct { USN int64 `json:"usn"` Name string `json:"name"` AccessToken string `json:"accessToken"` RefreshToken string `json:"refreshToken"` } func Login(c *gin.Context) { req := &LoginReq{} if err := c.ShouldBindJSON(req); err != nil { http_resp.JsonBadRequest(c) return } client, err := grpc_client.UserNewClientLB() if err != nil { log.Errorf("Login UserNewClientLB error: %v", err) http_resp.JsonOK(c, http_resp.Error(http_resp.Failed)) return } usn, name := int64(0), "" if req.Phone != "" { // TODO 校验验证码 login, err := client.PhoneLogin(c, &grpc_pb.PhoneLoginReq{ Phone: req.Phone, Code: req.Code, }) if err != nil { log.Errorf("Login PhoneLogin error: %v", err) http_resp.JsonOK(c, http_resp.Error(http_resp.Failed)) return } usn, name = login.USN, login.Name } else if req.WxMiniCode != "" { login, err := client.WxMiniLogin(c, &grpc_pb.WxMiniLoginReq{ Code: req.WxMiniCode, }) if err != nil { log.Errorf("Login WxMiniLogin error: %v", err) http_resp.JsonOK(c, http_resp.Error(http_resp.Failed)) return } usn, name = login.USN, login.Name } else { http_resp.JsonBadRequest(c) return } at, rt, err := genToken(c, usn) http_resp.JsonOK(c, http_resp.Success(&LoginResp{ USN: usn, Name: name, AccessToken: at, RefreshToken: rt, })) } type RefreshTokenReq struct { RefreshToken string `json:"refreshToken" binding:"required,min=1"` } type RefreshTokenResp struct { AccessToken string `json:"accessToken"` RefreshToken string `json:"refreshToken"` } func RefreshToken(c *gin.Context) { req := &RefreshTokenReq{} if err := c.ShouldBindJSON(req); err != nil { http_resp.JsonBadRequest(c) return } claims, err := utils.ParseToken(req.RefreshToken, config.Get().Auth.Secret) if err != nil { http_resp.JsonUnauthorized(c) return } if redis.GetClient().Get(c, fmt.Sprintf(global.KeyGatewayRefreshToken, claims.USN)).Val() != req.RefreshToken { http_resp.JsonUnauthorized(c) return } at, rt, err := genToken(c, claims.USN) if err != nil { log.Errorf("RefreshToken genToken error: %v, usn: %v", err, claims.USN) http_resp.JsonOK(c, http_resp.Error(http_resp.Failed)) return } http_resp.JsonOK(c, http_resp.Success(&RefreshTokenResp{ AccessToken: at, RefreshToken: rt, })) } func genToken(ctx context.Context, usn int64) (string, string, error) { at, err := genTokenOne(ctx, global.KeyGatewayAccessToken, usn, time.Duration(config.Get().Auth.ShortExpire)*time.Minute) if err != nil { return "", "", err } rt, err := genTokenOne(ctx, global.KeyGatewayRefreshToken, usn, time.Duration(config.Get().Auth.LongExpire)*time.Minute) if err != nil { return "", "", err } return at, rt, nil } func genTokenOne(ctx context.Context, key string, usn int64, ttl time.Duration) (string, error) { token, err := utils.GenToken(usn, config.Get().Auth.Secret, ttl) if err != nil { return "", err } redis.GetClient().Set(ctx, fmt.Sprintf(key, usn), token, ttl) return token, err }