🐛 fix the casbin invalidation bug/adjust routing strategy

This commit is contained in:
landaiqing
2024-09-04 18:58:13 +08:00
parent b6dafddce1
commit 2eb9c3ac68
24 changed files with 243 additions and 113 deletions

View File

@@ -1,27 +1,40 @@
package middleware
import (
ginI18n "github.com/gin-contrib/i18n"
"github.com/gin-gonic/gin"
"schisandra-cloud-album/common/result"
"schisandra-cloud-album/global"
)
func CasbinMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
userId, ok := c.Get("userId")
if !ok {
userIdAny, exists := c.Get("userId")
if !exists {
global.LOG.Error("casbin middleware: userId not found")
result.FailWithMessage(ginI18n.MustGetMessage(c, "PermissionDenied"), c)
c.Abort()
return
}
userId, ok := userIdAny.(*string)
if !ok {
result.FailWithMessage(ginI18n.MustGetMessage(c, "PermissionDenied"), c)
global.LOG.Error("casbin middleware: userId is not string")
c.Abort()
return
}
userIdStr := *userId
method := c.Request.Method
path := c.Request.URL.Path
ok, err := global.Casbin.Enforce(userId.(string), path, method)
correct, err := global.Casbin.Enforce(userIdStr, path, method)
if err != nil {
result.FailWithMessage(ginI18n.MustGetMessage(c, "PermissionDenied"), c)
global.LOG.Error("casbin middleware: ", err)
c.Abort()
return
}
if !ok {
if !correct {
result.FailWithMessage(ginI18n.MustGetMessage(c, "PermissionDenied"), c)
c.Abort()
return
}

View File

@@ -0,0 +1,31 @@
package middleware
import (
ginI18n "github.com/gin-contrib/i18n"
"github.com/gin-gonic/gin"
"schisandra-cloud-album/common/constant"
"schisandra-cloud-album/common/redis"
"schisandra-cloud-album/common/result"
"schisandra-cloud-album/utils"
)
// CheckClientMiddleware 检查客户端请求是否合法
func CheckClientMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
id := c.GetHeader("X-Request-Id")
if id == "" {
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyFailed"), c)
c.Abort()
return
}
ip := utils.GetClientIP(c)
clientId := redis.Get(constant.UserLoginClientRedisKey + ip).Val()
if clientId == "" || clientId != id {
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyFailed"), c)
c.Abort()
return
}
c.Next()
}
}

View File

@@ -1,35 +1,60 @@
package middleware
import (
"encoding/json"
ginI18n "github.com/gin-contrib/i18n"
"github.com/gin-gonic/gin"
"schisandra-cloud-album/common/constant"
"schisandra-cloud-album/common/redis"
"schisandra-cloud-album/common/result"
"schisandra-cloud-album/global"
"schisandra-cloud-album/utils"
"strings"
)
type TokenData struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresAt int64 `json:"expires_at"`
UID *string `json:"uid"`
}
func JWTAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 默认双Token放在请求头Authorization的Bearer中并以空格隔开
authHeader := c.GetHeader(global.CONFIG.JWT.HeaderKey)
if authHeader == "" {
c.Abort()
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyFailed"), c)
c.Abort()
return
}
headerPrefix := global.CONFIG.JWT.HeaderPrefix
accessToken := strings.TrimPrefix(authHeader, headerPrefix+" ")
if accessToken == "" {
c.Abort()
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyFailed"), c)
c.Abort()
return
}
parseToken, isUpd, err := utils.ParseAccessToken(accessToken)
if err != nil || !isUpd {
c.Abort()
result.FailWithCodeAndMessage(401, ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
c.Abort()
return
}
token := redis.Get(constant.UserLoginTokenRedisKey + *parseToken.UserID).Val()
tokenResult := TokenData{}
err = json.Unmarshal([]byte(token), &tokenResult)
if err != nil {
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
c.Abort()
return
}
if tokenResult.AccessToken != accessToken {
result.FailWithCodeAndMessage(403, ginI18n.MustGetMessage(c, "DuplicateLogin"), c)
c.Abort()
return
}
c.Set("userId", parseToken.UserID)