fusenapi/utils/auth/user.go
2023-06-14 18:17:45 +08:00

163 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package auth
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"github.com/golang-jwt/jwt"
"github.com/zeromicro/go-zero/core/logx"
)
type IDTYPE int
const (
// 白板用户, 以观众身份命名, 没有接收Cookie, 没有拿到guest_id的用户
IDTYPE_Onlooker IDTYPE = 0
// 登录用户
IDTYPE_User IDTYPE = 1
// 游客 接收授权拿到guest_id的用户
IDTYPE_Guest IDTYPE = 2
)
type UserInfo struct {
UserId int64 `json:"user_id"`
GuestId int64 `json:"guest_id"`
}
// GetIdType 用户确认用户身份类型
func (info *UserInfo) GetIdType() IDTYPE {
if info.UserId != 0 {
return IDTYPE_User
}
if info.GuestId != 0 {
return IDTYPE_Guest
}
return IDTYPE_Onlooker
}
// 获取登录信息
func GetUserInfoFormCtx(ctx context.Context) UserInfo {
uid, err := ctx.Value("user_id").(json.Number).Int64()
if err != nil {
logx.Error("parse uid form context err:", err.Error())
return UserInfo{}
}
return UserInfo{UserId: uid}
}
// 获取登录信息
func GetUserInfoFormMapClaims(claims jwt.MapClaims) (*UserInfo, error) {
userinfo := &UserInfo{}
if userid, ok := claims["user_id"]; ok {
uid, ok := userid.(float64)
if !ok {
err := errors.New(fmt.Sprint("parse uid form context err:", userid))
logx.Error("parse uid form context err:", err)
return nil, err
}
userinfo.UserId = int64(uid)
} else {
err := errors.New(`userid not in claims`)
logx.Error(`userid not in claims`)
return nil, err
}
if guestid, ok := claims["guest_id"]; ok {
gid, ok := guestid.(float64)
if !ok {
err := errors.New(fmt.Sprint("parse guestid form context err:", guestid))
logx.Error("parse guestid form context err:", err)
return nil, err
}
userinfo.GuestId = int64(gid)
} else {
err := errors.New(`userid not in claims`)
logx.Error(`userid not in claims`)
return nil, err
}
return userinfo, nil
}
func GenerateJwtToken(accessSecret *string, accessExpire, nowSec int64, userid int64, guestid int64) (string, error) {
claims := make(jwt.MapClaims)
claims["exp"] = nowSec + accessExpire
claims["iat"] = nowSec
if userid == 0 && guestid == 0 {
err := errors.New("userid and guestid cannot be 0 at the same time")
logx.Error(err)
return "", err
}
claims["user_id"] = userid
claims["guest_id"] = guestid
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte(*accessSecret))
}
func ParseJwtToken(w http.ResponseWriter, r *http.Request, AccessSecret *string) (*UserInfo, error) {
// 解析jwtToken
claims, err := getJwtClaimsFromRequest(r, AccessSecret)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
if err != nil {
// httpx.OkJsonCtx(r.Context(), w, &basic.Response{
// Code: 401,
// Message: "unauthorized",
// })
// logx.Info("unauthorized:", err.Error())
return nil, err
}
// 从Token里获取对应的信息
userinfo, err := GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错则返回未授权的JSON响应并记录错误消息
if err != nil {
// httpx.OkJsonCtx(r.Context(), w, &basic.Response{
// Code: 401,
// Message: "unauthorized",
// })
// logx.Info("unauthorized:", err.Error())
return nil, err
}
return userinfo, err
}
func getJwtClaimsFromRequest(r *http.Request, AccessSecret *string) (jwt.MapClaims, error) {
AuthKey := r.Header.Get("Authorization")
if len(AuthKey) <= 50 {
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
}
return getJwtClaims(AuthKey, AccessSecret)
}
func getJwtClaims(AuthKey string, AccessSecret *string) (jwt.MapClaims, error) {
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
// 检查签名方法是否为 HS256
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
// 返回用于验证签名的密钥
return []byte(*AccessSecret), nil
})
if err != nil {
return nil, errors.New(fmt.Sprint("Error parsing token:", err))
}
// 验证成功返回
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New(fmt.Sprint("Invalid token", err))
}