🐛 resolve interface validation issues

This commit is contained in:
landaiqing
2024-09-05 17:06:10 +08:00
parent 2eb9c3ac68
commit 01305c2fa7
10 changed files with 68 additions and 89 deletions

View File

@@ -8,6 +8,7 @@ import (
"schisandra-cloud-album/common/result"
"schisandra-cloud-album/global"
"schisandra-cloud-album/utils"
"time"
)
// GenerateClientId 生成客户端ID
@@ -29,10 +30,9 @@ func (ClientAPI) GenerateClientId(c *gin.Context) {
result.OkWithData(clientId, c)
return
}
// 生成新的客户端ID
v1 := uuid.NewV1()
err := redis.Set(constant.UserLoginClientRedisKey+ip, v1.String(), 0).Err()
err := redis.Set(constant.UserLoginClientRedisKey+ip, v1.String(), time.Hour*24*30).Err()
if err != nil {
global.LOG.Error(err)
return

View File

@@ -125,9 +125,8 @@ func (OAuthAPI) GetTempQrCode(c *gin.Context) {
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
return
}
ip := utils.GetClientIP(c) // 使用工具函数获取客户端IP
key := constant.UserLoginQrcodeRedisKey + ip + ":" + clientId
key := constant.UserLoginQrcodeRedisKey + ip
// 从Redis获取二维码数据
qrcode := redis.Get(key).Val()

View File

@@ -69,7 +69,7 @@ func (PermissionAPI) AssignPermissionsToRole(c *gin.Context) {
return
}
// GetUserPermissions 获取用权限
// GetUserPermissions 获取用户角色权限
func (PermissionAPI) GetUserPermissions(c *gin.Context) {
userId := c.Query("user_id")
if userId == "" {
@@ -78,6 +78,7 @@ func (PermissionAPI) GetUserPermissions(c *gin.Context) {
}
data, err := global.Casbin.GetImplicitRolesForUser(userId)
if err != nil {
result.FailWithMessage(ginI18n.MustGetMessage(c, "GetUserFailed"), c)
return
}
result.OkWithData(data, c)

View File

@@ -498,3 +498,35 @@ func getUserLoginDevice(user model.ScaAuthUser, c *gin.Context) bool {
return true
}
// Logout 退出登录
// @Summary 退出登录
// @Tags 用户模块
// @Success 200 {string} json
// @Router /api/auth/user/logout [post]
func (UserAPI) Logout(c *gin.Context) {
userId := c.Query("user_id")
if userId == "" {
global.LOG.Errorln("userId is empty")
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
return
}
tokenKey := constant.UserLoginTokenRedisKey + userId
del := redis.Del(tokenKey)
if del.Err() != nil {
global.LOG.Errorln(del.Err())
result.FailWithMessage(ginI18n.MustGetMessage(c, "LogoutFailed"), c)
return
}
ip := utils.GetClientIP(c)
key := constant.UserLoginClientRedisKey + ip
del = redis.Del(key)
if del.Err() != nil {
global.LOG.Errorln(del.Err())
result.FailWithMessage(ginI18n.MustGetMessage(c, "LogoutFailed"), c)
return
}
result.OkWithMessage(ginI18n.MustGetMessage(c, "LogoutSuccess"), c)
}

View File

@@ -58,3 +58,5 @@ AssignFailed = "assign failed!"
AssignSuccess = "assign successfully!"
DuplicateLogin = "duplicate login!"
PermissionDenied = "permission denied!"
LogoutFailed = "logout failed!"
LogoutSuccess = "logout successfully!"

View File

@@ -58,4 +58,5 @@ AssignFailed = "分配失败!"
AssignSuccess = "分配成功!"
DuplicateLogin = "重复登录!"
PermissionDenied = "权限不足!"
LogoutFailed = "登出失败!"
LogoutSuccess = "登出成功!"

View File

@@ -1,31 +0,0 @@
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,26 +0,0 @@
package middleware
import (
"github.com/gin-gonic/gin"
"net/http"
)
// Cors 自定义跨域中间件
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
origin := c.Request.Header.Get("Origin")
if origin != "" {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization")
c.Header("Access-Control-Allow-Credentials", "true")
c.Set("content-type", "application/json")
}
//放行所有OPTIONS方法
if method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
}
c.Next()
}
}

View File

@@ -24,8 +24,7 @@ func JWTAuthMiddleware() gin.HandlerFunc {
// 默认双Token放在请求头Authorization的Bearer中并以空格隔开
authHeader := c.GetHeader(global.CONFIG.JWT.HeaderKey)
if authHeader == "" {
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyFailed"), c)
result.FailWithCodeAndMessage(403, ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
c.Abort()
return
}
@@ -33,11 +32,11 @@ func JWTAuthMiddleware() gin.HandlerFunc {
accessToken := strings.TrimPrefix(authHeader, headerPrefix+" ")
if accessToken == "" {
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyFailed"), c)
result.FailWithCodeAndMessage(403, ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
c.Abort()
return
}
parseToken, isUpd, err := utils.ParseAccessToken(accessToken)
if err != nil || !isUpd {
result.FailWithCodeAndMessage(401, ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
@@ -45,15 +44,20 @@ func JWTAuthMiddleware() gin.HandlerFunc {
return
}
token := redis.Get(constant.UserLoginTokenRedisKey + *parseToken.UserID).Val()
if token == "" {
result.FailWithCodeAndMessage(403, ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
c.Abort()
return
}
tokenResult := TokenData{}
err = json.Unmarshal([]byte(token), &tokenResult)
if err != nil {
result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
result.FailWithCodeAndMessage(403, ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
c.Abort()
return
}
if tokenResult.AccessToken != accessToken {
result.FailWithCodeAndMessage(403, ginI18n.MustGetMessage(c, "DuplicateLogin"), c)
result.FailWithCodeAndMessage(403, ginI18n.MustGetMessage(c, "AuthVerifyExpired"), c)
c.Abort()
return
}

View File

@@ -25,7 +25,7 @@ func InitRouter() *gin.Engine {
router.Use(cors.New(cors.Config{
AllowOrigins: []string{global.CONFIG.System.Web},
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"},
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization", "X-CSRF-Token", "Accept-Language", "X-Request-Id"},
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization", "Accept-Language"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))
@@ -33,28 +33,25 @@ func InitRouter() *gin.Engine {
router.Use(middleware.I18n())
publicGroup := router.Group("api") // 不需要鉴权的路由组
authGroup := router.Group("api") // 需要鉴权的路由组
{
modules.ClientRouter(publicGroup) // 注册客户端路由
modules.SwaggerRouter(publicGroup) // 注册swagger路由
modules.WebsocketRouter(publicGroup) // 注册websocket路由
modules.OauthRouter(publicGroup)
modules.CaptchaRouter(publicGroup) // 注册验证码路由
modules.SmsRouter(publicGroup) // 注册短信验证码路由
modules.UserRouter(publicGroup) // 注册鉴权路由
}
authGroup := router.Group("api") // 需要鉴权的路由组
authGroup.Use(
middleware.JWTAuthMiddleware(),
middleware.CasbinMiddleware(),
middleware.CheckClientMiddleware())
checkClientGroup := router.Group("api") // 需要检查客户端的路由
checkClientGroup.Use(middleware.CheckClientMiddleware())
modules.ClientRouter(publicGroup) // 注册客户端路由
modules.SwaggerRouter(publicGroup) // 注册swagger路由
modules.WebsocketRouter(publicGroup) // 注册websocket路由
modules.CaptchaRouter(checkClientGroup) // 注册验证码路由
modules.SmsRouter(checkClientGroup) // 注册短信验证码路由
modules.OauthRouter(checkClientGroup) // 注册oauth路由
modules.UserRouter(checkClientGroup) // 注册鉴权路由
modules.UserRouterAuth(authGroup) // 注册鉴权路由
modules.RoleRouter(authGroup) // 注册角色路由
modules.PermissionRouter(authGroup) // 注册权限路由
)
{
modules.UserRouterAuth(authGroup) // 注册鉴权路由
modules.RoleRouter(authGroup) // 注册角色路由
modules.PermissionRouter(authGroup) // 注册权限路由
}
return router
}