You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.8 KiB

3 months ago
package initialize
import (
"context"
"github.com/cloudwego/hertz/pkg/protocol"
"strings"
"time"
"github.com/hertz-contrib/jwt"
"github.com/TremblingV5/DouTok/applications/api/biz/model/api"
"github.com/TremblingV5/DouTok/applications/api/initialize/rpc"
"github.com/TremblingV5/DouTok/kitex_gen/user"
"github.com/TremblingV5/DouTok/pkg/constants"
"github.com/TremblingV5/DouTok/pkg/errno"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
var AuthMiddleware *jwt.HertzJWTMiddleware
type LoginResp struct {
StatusCode int `json:"status_code"`
StatusMsg string `json:"status_msg"`
UserId int64 `json:"user_id,string"`
Token string `json:"token"`
}
func InitJwt() {
AuthMiddleware, _ = jwt.New(&jwt.HertzJWTMiddleware{
Key: []byte(ViperConfig.Viper.GetString("JWT.signingKey")),
Timeout: 12 * time.Hour,
MaxRefresh: time.Hour,
PayloadFunc: func(data interface{}) jwt.MapClaims {
if v, ok := data.(int64); ok {
return jwt.MapClaims{
constants.IdentityKey: v,
}
}
return jwt.MapClaims{}
},
HTTPStatusMessageFunc: func(e error, ctx context.Context, c *app.RequestContext) string {
switch e.(type) { //nolint
case errno.ErrNo:
return e.(errno.ErrNo).ErrMsg //nolint
default:
return e.Error()
}
},
LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) {
claims := jwt.ExtractClaims(ctx, c)
// Long 型数据在返回前端时会失真,需使用string类型
//userId := strconv.FormatInt(claims[constants.IdentityKey].(int64), 10)
c.SetCookie("token", token, 24*60*60, "/", "", protocol.CookieSameSiteDefaultMode, false, true)
userId := claims[constants.IdentityKey].(int64)
c.JSON(consts.StatusOK, LoginResp{
StatusCode: errno.SuccessCode,
StatusMsg: errno.Success.ErrMsg,
UserId: userId,
Token: token,
})
},
WithNext: func(ctx context.Context, c *app.RequestContext) bool {
if strings.Contains(string(c.Request.Path()), "feed") {
var req api.DouyinFeedRequest
err := c.BindAndValidate(&req)
if err == nil && req.Token == "" {
return true
}
return false
}
//if strings.Contains(string(c.Request.Path()), "publish") {
// tokenInForm := string(c.FormValue("token"))
//
// if tokenInForm != "" {
// jwt1.Parse(tokenInForm, func(token *jwt1.Token) (interface{}, error) {
// if _, ok := token.Method.(*jwt1.SigningMethodRSA); !ok {
// return nil, errors.New("unsupported signing method")
// }
// return
// })
// return true
// }
//
// return false
//}
return false
},
IdentityKey: constants.IdentityKey,
IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} {
claims := jwt.ExtractClaims(ctx, c)
return claims[constants.IdentityKey].(float64)
},
Unauthorized: func(ctx context.Context, c *app.RequestContext, code int, message string) {
c.JSON(code, map[string]interface{}{
"status_code": errno.AuthorizationFailedErrCode,
"status_msg": message,
})
},
Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) {
var loginVar api.DouyinUserLoginRequest
if err := c.Bind(&loginVar); err != nil {
return "", jwt.ErrMissingLoginValues
}
if len(loginVar.Username) == 0 || len(loginVar.Password) == 0 {
return "", jwt.ErrMissingLoginValues
}
userId, err := rpc.Login(context.Background(), rpc.UserClient, &user.DouyinUserLoginRequest{Username: loginVar.Username, Password: loginVar.Password})
if err == nil && userId != 0 {
c.Set("JWT_PAYLOAD", jwt.MapClaims{
constants.IdentityKey: userId,
})
}
return userId, err
},
TokenLookup: "query: token, form: token, param: token, cookie: token",
TimeFunc: time.Now,
})
}