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.
75 lines
2.1 KiB
75 lines
2.1 KiB
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"laic-backend/cache"
|
|
"laic-backend/common"
|
|
"laic-backend/token"
|
|
)
|
|
|
|
// AuthMiddleware 鉴权中间件:解析 JWT + Redis 存证校验 + 注入上下文
|
|
func AuthMiddleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
tokenString := c.GetHeader("Authorization")
|
|
if tokenString == "" {
|
|
common.FailWithBusiErrorWithHttpStatus(c, http.StatusUnauthorized, common.ErrUnauthorized)
|
|
return
|
|
}
|
|
tokenString = strings.TrimPrefix(tokenString, "Bearer ")
|
|
if tokenString == "" {
|
|
common.FailWithBusiErrorWithHttpStatus(c, http.StatusUnauthorized, common.ErrUnauthorized)
|
|
return
|
|
}
|
|
|
|
claims, err := token.ParseToken(tokenString)
|
|
if err != nil {
|
|
common.FailWithBusiErrorWithHttpStatus(c, http.StatusUnauthorized, common.ErrToken)
|
|
return
|
|
}
|
|
|
|
// Redis 存证校验:登出会删除该 key,从而让已签发 token 失效
|
|
storeKey := cache.UserTokenKeyOf(claims.UserID, token.GenerateShortID(tokenString))
|
|
if !common.HasKey(storeKey) {
|
|
common.FailWithBusiErrorWithHttpStatus(c, http.StatusUnauthorized, common.SignOutToken)
|
|
return
|
|
}
|
|
|
|
roles := claims.Roles
|
|
if roles == nil {
|
|
roles = []string{}
|
|
}
|
|
isAdmin := slices.Contains(roles, common.RoleAdmin)
|
|
c.Set("user_id", claims.UserID)
|
|
c.Set("username", claims.Username)
|
|
c.Set("roles", roles)
|
|
c.Set("is_admin", isAdmin)
|
|
|
|
// Casbin 权限校验(admin 与普通用户均按 p/g 策略校验,admin 仅限平台管理职能)
|
|
if common.CasbinEnforcer != nil {
|
|
ok, err := common.CasbinEnforcer.Enforce(strconv.FormatInt(claims.UserID, 10), c.Request.URL.Path, c.Request.Method)
|
|
if err != nil || !ok {
|
|
common.FailWithBusiErrorWithHttpStatus(c, http.StatusForbidden, common.ErrForbidden)
|
|
c.Abort()
|
|
return
|
|
}
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// AdminMiddleware 仅管理员可访问
|
|
func AdminMiddleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
if !c.GetBool("is_admin") {
|
|
common.FailWithBusiErrorWithHttpStatus(c, http.StatusForbidden, common.ErrForbidden)
|
|
return
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|