Files
service-gateway/internal/handler/http_handler/login.go

120 lines
3.2 KiB
Go

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/service"
"git.hlsq.asia/mmorpg/service-common/net/http/http_resp"
"git.hlsq.asia/mmorpg/service-common/proto/ss/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" binding:"required,min=1"`
Code string `json:"code" binding:"required,min=1"`
}
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 := service.UserNewClientLB()
if err != nil {
log.Errorf("Login UserNewClientLB error: %v", err)
http_resp.JsonOK(c, http_resp.Error(http_resp.Failed))
return
}
login, err := client.Login(c, &grpc_pb.LoginReq{
Phone: req.Phone,
Code: req.Code,
})
if err != nil {
log.Errorf("Login Login error: %v", err)
http_resp.JsonOK(c, http_resp.Error(http_resp.Failed))
return
}
at, rt, err := genToken(c, login.USN)
http_resp.JsonOK(c, http_resp.Success(&LoginResp{
USN: login.USN,
Name: login.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.JsonOK(c, http_resp.Error(http_resp.TokenInvalid))
return
}
if redis.GetClient().Get(c, fmt.Sprintf(global.KeyGatewayRefreshToken, claims.USN)).Val() != req.RefreshToken {
http_resp.JsonOK(c, http_resp.Error(http_resp.TokenInvalid))
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, 2*time.Hour)
if err != nil {
return "", "", err
}
rt, err := genTokenOne(ctx, global.KeyGatewayRefreshToken, usn, 3*24*time.Hour)
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, time.Duration(config.Get().Auth.Expire)*time.Second)
if err != nil {
return "", err
}
redis.GetClient().Set(ctx, fmt.Sprintf(key, usn), token, ttl)
return token, err
}