179 lines
5.4 KiB
Go
179 lines
5.4 KiB
Go
|
|
package middleware
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"fmt"
|
|||
|
|
"time"
|
|||
|
|
|
|||
|
|
"go-admin/common/middleware/handler"
|
|||
|
|
rediskey "go-admin/common/redis_key"
|
|||
|
|
"go-admin/common/statuscode"
|
|||
|
|
"go-admin/utils/redishelper"
|
|||
|
|
|
|||
|
|
"github.com/gin-gonic/gin"
|
|||
|
|
"github.com/go-admin-team/go-admin-core/sdk/config"
|
|||
|
|
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// AuthInit jwt验证new
|
|||
|
|
func AuthInit() (*jwt.GinJWTMiddleware, error) {
|
|||
|
|
timeout := time.Hour
|
|||
|
|
if config.ApplicationConfig.Mode == "dev" {
|
|||
|
|
timeout = time.Duration(876010) * time.Hour
|
|||
|
|
} else {
|
|||
|
|
if config.JwtConfig.Timeout != 0 {
|
|||
|
|
timeout = time.Duration(config.JwtConfig.Timeout) * time.Second
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return jwt.New(&jwt.GinJWTMiddleware{
|
|||
|
|
Realm: "test zone",
|
|||
|
|
Key: []byte(config.JwtConfig.Secret),
|
|||
|
|
Timeout: timeout,
|
|||
|
|
MaxRefresh: time.Hour,
|
|||
|
|
PayloadFunc: handler.PayloadFunc,
|
|||
|
|
IdentityHandler: handler.IdentityHandler,
|
|||
|
|
Authenticator: handler.Authenticator,
|
|||
|
|
Authorizator: handler.Authorizator,
|
|||
|
|
Unauthorized: handler.Unauthorized,
|
|||
|
|
TokenLookup: "header: Authorization, query: token, cookie: jwt",
|
|||
|
|
TokenHeadName: "Bearer",
|
|||
|
|
TimeFunc: time.Now,
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// apikey授权认证
|
|||
|
|
func FrontedAuth(c *gin.Context) {
|
|||
|
|
// 从请求头中获取 token 和 os
|
|||
|
|
apikey := c.GetHeader("x-api-key")
|
|||
|
|
// 如果 token 不存在,返回未登录的状态
|
|||
|
|
if len(apikey) == 0 {
|
|||
|
|
err := ResponseWithStatus(c, statuscode.Unauthorized)
|
|||
|
|
if err != nil {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
c.Abort() // 停止后续中间件的执行
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
// 验证 token 并获取结果
|
|||
|
|
key := fmt.Sprintf(rediskey.TM_MEMBER_BY_KEY, apikey)
|
|||
|
|
val, err := redishelper.DefaultRedis.GetString(key)
|
|||
|
|
|
|||
|
|
if err != nil || val == "" {
|
|||
|
|
ResponseWithStatus(c, statuscode.Unauthorized)
|
|||
|
|
c.Abort() // 停止后续中间件的执行
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 将解析后的 token 设置到请求头中
|
|||
|
|
c.Set("apiKey", apikey)
|
|||
|
|
// 继续处理请求
|
|||
|
|
c.Next()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ResponseWithStatus 带状态的响应
|
|||
|
|
func ResponseWithStatus(ctx *gin.Context, code int, data ...interface{}) error {
|
|||
|
|
// 获取语言对应的 msg
|
|||
|
|
// msg := statuscode.GetStatusCodeDescription(ctx, code)
|
|||
|
|
// if msg == `` {
|
|||
|
|
// msg = strconv.Itoa(code)
|
|||
|
|
// } else {
|
|||
|
|
// // 配置了语言包参数
|
|||
|
|
// if strings.Contains(msg, "%") && len(data) > 1 {
|
|||
|
|
// msg = fmt.Sprintf(msg, data[1:]...)
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
resp := statuscode.Response{
|
|||
|
|
Code: code,
|
|||
|
|
Msg: "un authorized",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// resp.RequestID = pkg.GenerateMsgIDFromContext(ctx)
|
|||
|
|
if len(data) > 0 {
|
|||
|
|
resp.Data = data[0]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch code {
|
|||
|
|
case 401, 500, 405, 404:
|
|||
|
|
ctx.JSON(code, resp)
|
|||
|
|
default:
|
|||
|
|
ctx.JSON(200, resp)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// func AuthApiInit() (*jwt.GinJWTMiddleware, error) gin.HandlerFunc {
|
|||
|
|
// return func(c *gin.Context) {
|
|||
|
|
// // 1. 从请求头或查询参数中获取 API Key
|
|||
|
|
// // 优先从 Header "X-API-Key" 获取,其次从查询参数 "api_key" 获取
|
|||
|
|
// apiKey := c.GetHeader("X-API-Key")
|
|||
|
|
// if apiKey == "" {
|
|||
|
|
// apiKey = c.Query("api_key")
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// // 2. 检查 API Key 是否存在
|
|||
|
|
// if apiKey == "" {
|
|||
|
|
// logger.Debug("API Key not provided in header or query parameter.")
|
|||
|
|
// response.Unauthorized(c, "API Key is required.")
|
|||
|
|
// c.Abort() // 终止请求处理链
|
|||
|
|
// return
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// // 3. 验证 API Key 的有效性
|
|||
|
|
// // 实际项目中,这里需要查询数据库或缓存来验证 API Key,并获取其关联的用户ID或权限
|
|||
|
|
// // 伪代码示例:
|
|||
|
|
// // user, isValid := service.AuthService.ValidateApiKey(apiKey)
|
|||
|
|
// // if !isValid {
|
|||
|
|
// // response.Unauthorized(c, "Invalid API Key.")
|
|||
|
|
// // c.Abort()
|
|||
|
|
// // return
|
|||
|
|
// // }
|
|||
|
|
// // c.Set("user_id", user.ID) // 将关联的用户ID设置到 Gin Context 中
|
|||
|
|
|
|||
|
|
// // 简化示例:从配置中获取一个硬编码的有效 API Key
|
|||
|
|
// // **警告:生产环境中,绝不能硬编码 API Key!这只是一个演示。**
|
|||
|
|
// // 假设 config.APIKeyConfig.ValidKeys 是一个 map[string]string,存储 apiKey -> userID 的映射
|
|||
|
|
// // 或者 config.APIKeyConfig.MasterKey 是一个单一的预设主密钥
|
|||
|
|
|
|||
|
|
// isValid := false
|
|||
|
|
// associatedUserID := "" // 存储与 API Key 关联的用户ID
|
|||
|
|
|
|||
|
|
// // 假设 API Key 存储在 config.APIKeyConfig 中,例如:
|
|||
|
|
// // type APIKeyConfig struct {
|
|||
|
|
// // MasterKey string `mapstructure:"master_key"`
|
|||
|
|
// // ValidKeys map[string]string `mapstructure:"valid_keys"` // key: API Key, value: UserID
|
|||
|
|
// // }
|
|||
|
|
// // 你可能需要根据你的 config.go 中 API Key 配置的实际结构来调整
|
|||
|
|
|
|||
|
|
// // 示例:检查是否是 MasterKey
|
|||
|
|
// if apiKey == config.APIKeyConfig.MasterKey { // 假设你有一个MasterKey
|
|||
|
|
// isValid = true
|
|||
|
|
// associatedUserID = "platform_admin" // 或者一个特殊的管理员ID
|
|||
|
|
// } else {
|
|||
|
|
// // 示例:检查是否在有效键列表中
|
|||
|
|
// for key, uid := range config.APIKeyConfig.ValidKeys { // 假设 ValidKeys 是一个 map
|
|||
|
|
// if apiKey == key {
|
|||
|
|
// isValid = true
|
|||
|
|
// associatedUserID = uid
|
|||
|
|
// break
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// if !isValid {
|
|||
|
|
// logger.Warnf("Attempted to use invalid API Key: %s", apiKey)
|
|||
|
|
// response.Unauthorized(c, "Invalid API Key.")
|
|||
|
|
// c.Abort()
|
|||
|
|
// return
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// // 4. API Key 验证成功,将关联的用户ID或信息设置到 Gin Context
|
|||
|
|
// // 这样后续的业务逻辑(如翻译服务中的扣费)就可以通过 c.GetString("user_id") 获取到用户身份
|
|||
|
|
// c.Set("user_id", associatedUserID)
|
|||
|
|
// logger.Debugf("API Key authenticated successfully for user: %s", associatedUserID)
|
|||
|
|
|
|||
|
|
// // 5. 继续处理请求
|
|||
|
|
// c.Next()
|
|||
|
|
// }
|
|||
|
|
// }
|