🎨 重构用户端前端为vue开发,完善基础类和角色相关接口
This commit is contained in:
147
server/middleware/app_jwt.go
Normal file
147
server/middleware/app_jwt.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"git.echol.cn/loser/st/server/global"
|
||||
"git.echol.cn/loser/st/server/model/app"
|
||||
"git.echol.cn/loser/st/server/model/common/response"
|
||||
"git.echol.cn/loser/st/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
// AppJWTAuth 前台用户 JWT 认证中间件
|
||||
func AppJWTAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
token := GetToken(c)
|
||||
if token == "" {
|
||||
response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 解析 JWT
|
||||
claims, err := utils.ParseAppToken(token)
|
||||
if err != nil {
|
||||
if errors.Is(err, jwt.ErrTokenExpired) {
|
||||
response.FailWithDetailed(gin.H{"reload": true}, "Token 已过期", c)
|
||||
} else {
|
||||
response.FailWithDetailed(gin.H{"reload": true}, "Token 无效", c)
|
||||
}
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 验证用户类型(确保是前台用户)
|
||||
if claims.UserType != utils.UserTypeApp {
|
||||
response.FailWithMessage("无效的用户类型", c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 查询用户是否存在
|
||||
var user app.AppUser
|
||||
err = global.GVA_DB.Where("id = ?", claims.UserID).First(&user).Error
|
||||
if err != nil {
|
||||
response.FailWithMessage("用户不存在", c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户状态
|
||||
if !user.Enable {
|
||||
response.FailWithMessage("用户已被禁用", c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if user.Status != "active" {
|
||||
response.FailWithMessage("账户状态异常", c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 将用户信息存入上下文
|
||||
c.Set("appUserId", user.ID)
|
||||
c.Set("appUser", &user)
|
||||
c.Set("appUsername", user.Username)
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// GetAppUserID 从上下文获取前台用户 ID(需要鉴权的接口使用)
|
||||
func GetAppUserID(c *gin.Context) uint {
|
||||
if userID, exists := c.Get("appUserId"); exists {
|
||||
return userID.(uint)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetOptionalAppUserID 从上下文获取可选的前台用户 ID(公开接口使用)
|
||||
// 如果用户已登录,返回用户 ID;否则返回 nil
|
||||
func GetOptionalAppUserID(c *gin.Context) *uint {
|
||||
// 先尝试从上下文获取(通过鉴权中间件设置)
|
||||
if userID, exists := c.Get("appUserId"); exists {
|
||||
if id, ok := userID.(uint); ok {
|
||||
return &id
|
||||
}
|
||||
}
|
||||
|
||||
// 如果上下文中没有,尝试手动解析 Token(用于公开接口)
|
||||
token := GetToken(c)
|
||||
if token == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
claims, err := utils.ParseAppToken(token)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if claims.UserType != utils.UserTypeApp {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &claims.UserID
|
||||
}
|
||||
|
||||
// GetAppUser 从上下文获取前台用户信息
|
||||
func GetAppUser(c *gin.Context) *app.AppUser {
|
||||
if user, exists := c.Get("appUser"); exists {
|
||||
return user.(*app.AppUser)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAppUsername 从上下文获取前台用户名
|
||||
func GetAppUsername(c *gin.Context) string {
|
||||
if username, exists := c.Get("appUsername"); exists {
|
||||
return username.(string)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetToken 从请求中获取 Token
|
||||
// 优先从 Header 获取,其次从 Query 参数获取
|
||||
func GetToken(c *gin.Context) string {
|
||||
token := c.Request.Header.Get("x-token")
|
||||
if token == "" {
|
||||
token = c.Request.Header.Get("Authorization")
|
||||
if token != "" && len(token) > 7 && token[:7] == "Bearer " {
|
||||
token = token[7:]
|
||||
}
|
||||
}
|
||||
if token == "" {
|
||||
token = c.Query("token")
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
// SetAppUserID 设置用户 ID 到上下文(用于某些特殊场景)
|
||||
func SetAppUserID(c *gin.Context, userID uint) {
|
||||
c.Set("appUserId", userID)
|
||||
c.Set("appUserIdStr", strconv.Itoa(int(userID)))
|
||||
}
|
||||
Reference in New Issue
Block a user