first commit
This commit is contained in:
97
middle/middle_auth.go
Normal file
97
middle/middle_auth.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// Package middle auth_middleware.go
|
||||
package middle
|
||||
|
||||
import (
|
||||
"Quincy_admin/utils"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AuthMiddleware struct {
|
||||
Service *MService
|
||||
}
|
||||
|
||||
func NewAuthMiddleware(Service *MService) *AuthMiddleware {
|
||||
return &AuthMiddleware{
|
||||
Service: Service,
|
||||
}
|
||||
}
|
||||
|
||||
// Auth 验证 X-Access-Token 的中间件
|
||||
func (m *AuthMiddleware) Auth() gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
|
||||
// 获取 X-Access-Token 头部
|
||||
token := ctx.GetHeader("Authorization")
|
||||
if token == "" {
|
||||
utils.Error(ctx, http.StatusUnauthorized, "缺少访问令牌")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
user, err := utils.ParseToken(token)
|
||||
if err != nil {
|
||||
utils.Error(ctx, http.StatusUnauthorized, "无效的访问令牌")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 验证用户是否存在
|
||||
newUser, err := m.Service.GetUserID(user.SessionCode)
|
||||
if err != nil {
|
||||
utils.Error(ctx, http.StatusUnauthorized, "用户不存在")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if newUser.Status != 1 {
|
||||
utils.Error(ctx, http.StatusUnauthorized, "用户已被锁定")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 使用 ctx.Set() 存储用户 ID,角色ID,供后续中间件读取
|
||||
ctx.Set("user_id", newUser.ID)
|
||||
ctx.Set("role_id", newUser.RoleCode)
|
||||
ctx.Set("code", newUser.SessionCode)
|
||||
|
||||
// token 验证成功,继续处理请求
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Perm 验证权限
|
||||
func (m *AuthMiddleware) Perm(perm string) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
|
||||
userIDInterface, exists := ctx.Get("user_id")
|
||||
if !exists {
|
||||
utils.Error(ctx, http.StatusUnauthorized, "权限校验错误:用户ID不存在")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
userID, ok := userIDInterface.(int)
|
||||
if !ok {
|
||||
utils.Error(ctx, http.StatusUnauthorized, "权限校验错误:用户ID类型错误")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否为超级管理员,如果是则跳过权限校验
|
||||
if m.Service.IsSuperAdmin(userID) {
|
||||
ctx.Next()
|
||||
return
|
||||
}
|
||||
|
||||
// 非超管账号检查权限
|
||||
if err := m.Service.HasPermission(userID, perm); err != nil {
|
||||
utils.Error(ctx, http.StatusForbidden, "没有权限")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
||||
23
middle/middle_cors.go
Normal file
23
middle/middle_cors.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Package middle auth_middleware.go
|
||||
package middle
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// SetupCORS 返回CORS中间件函数
|
||||
func SetupCORS() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization")
|
||||
c.Header("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
if c.Request.Method == "OPTIONS" {
|
||||
c.AbortWithStatus(204)
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
72
middle/middle_logger.go
Normal file
72
middle/middle_logger.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Package middle middle_logger.go
|
||||
package middle
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RequestResponseLogger() gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
// 保存原始请求体
|
||||
var bodyBytes []byte
|
||||
if ctx.Request.Body != nil {
|
||||
bodyBytes, _ = io.ReadAll(ctx.Request.Body)
|
||||
// 恢复请求体,供后续处理使用
|
||||
ctx.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
}
|
||||
|
||||
// 获取查询参数
|
||||
queryParams := ctx.Request.URL.Query().Encode()
|
||||
|
||||
// 获取请求头信息
|
||||
var headers string
|
||||
Token := ctx.GetHeader("X-Access-Token")
|
||||
|
||||
headers = fmt.Sprintf("X-Access-Token: %s; ", Token)
|
||||
|
||||
// 记录开始时间
|
||||
startTime := time.Now()
|
||||
|
||||
// 继续处理请求
|
||||
ctx.Next()
|
||||
|
||||
// 计算处理时间
|
||||
latency := time.Since(startTime)
|
||||
|
||||
// 格式化日志内容
|
||||
timestamp := time.Now().Format("2006/01/02 15:04:05")
|
||||
|
||||
// 格式化日志内容
|
||||
logMessage := fmt.Sprintf("[GIN] Request | %3d | %13v | %15s | %-7s %s",
|
||||
ctx.Writer.Status(),
|
||||
latency,
|
||||
ctx.ClientIP(),
|
||||
ctx.Request.Method,
|
||||
ctx.Request.URL.Path,
|
||||
)
|
||||
|
||||
// 单独打印查询参数(带时间戳)
|
||||
if queryParams != "" {
|
||||
logMessage += fmt.Sprintf("\n%s [GIN] Params: %s", timestamp, queryParams)
|
||||
}
|
||||
|
||||
// 单独打印请求体(带时间戳)
|
||||
if len(bodyBytes) > 0 {
|
||||
logMessage += fmt.Sprintf("\n%s [GIN] Body: %s", timestamp, string(bodyBytes))
|
||||
}
|
||||
|
||||
// 单独打印请求头(带时间戳)
|
||||
if headers != "" {
|
||||
logMessage += fmt.Sprintf("\n%s [GIN] Headers: %s", timestamp, headers)
|
||||
}
|
||||
|
||||
// 输出到控制台
|
||||
log.Println(logMessage)
|
||||
}
|
||||
}
|
||||
112
middle/middle_service.go
Normal file
112
middle/middle_service.go
Normal file
@@ -0,0 +1,112 @@
|
||||
// Package middle/middle_service.go
|
||||
package middle
|
||||
|
||||
import (
|
||||
"Quincy_admin/schemas"
|
||||
"fmt"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type MService struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func NewMiddleService(db *sqlx.DB) *MService {
|
||||
return &MService{db: db}
|
||||
}
|
||||
|
||||
// GetUserID 验证令牌并返回用户信息
|
||||
//func (s *MService) GetUserID(scode string) (*schemas.UserInfo, error) {
|
||||
// // 从Redis获取用户信息
|
||||
// InitRedis := utils.GetRedis()
|
||||
// ctx := utils.GetContext()
|
||||
//
|
||||
// // 尝试从Redis获取用户会话信息
|
||||
// userInfoStr, err := InitRedis.Get(ctx, scode).Result()
|
||||
// if err != nil {
|
||||
// // Redis中未找到会话信息,视为登录过期
|
||||
// return nil, fmt.Errorf("登录已过期")
|
||||
// }
|
||||
//
|
||||
// // 解析Redis中的用户信息
|
||||
// var user schemas.UserInfo
|
||||
// err = json.Unmarshal([]byte(userInfoStr), &user)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("会话信息解析失败")
|
||||
// }
|
||||
//
|
||||
// return &user, nil
|
||||
//}
|
||||
|
||||
// GetUserID 验证令牌并返回用户ID
|
||||
func (s *MService) GetUserID(scode string) (*schemas.UserInfo, error) {
|
||||
// 实现令牌验证逻辑
|
||||
query := `
|
||||
SELECT
|
||||
tb1.id,
|
||||
COALESCE(tb2.role_id, 0) AS rolecode,
|
||||
tb1.sessioncode,
|
||||
tb1.username,
|
||||
tb1.password,
|
||||
tb1.nickname,
|
||||
tb1.email,
|
||||
tb1.avatar,
|
||||
tb1.status,
|
||||
tb1.register_time,
|
||||
tb1.last_login_time
|
||||
FROM
|
||||
admin_user tb1
|
||||
JOIN admin_user_role tb2 ON tb1.id = tb2.user_id
|
||||
WHERE
|
||||
sessioncode = ?
|
||||
ORDER BY
|
||||
tb1.id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
user := &schemas.UserInfo{}
|
||||
err := s.db.Get(user, query, scode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// HasPermission 检查用户是否有特定权限
|
||||
func (s *MService) HasPermission(userID int, permission string) error {
|
||||
query := `
|
||||
SELECT
|
||||
COUNT(*) > 0 AS has_permission
|
||||
FROM
|
||||
admin_user au
|
||||
JOIN admin_user_role aur ON au.id = aur.user_id
|
||||
JOIN admin_role ar ON aur.role_id = ar.id
|
||||
JOIN admin_role_permission arp ON ar.id = arp.role_id
|
||||
JOIN admin_permission ap ON arp.permission_id = ap.id
|
||||
WHERE
|
||||
au.id = ?
|
||||
AND ap.name = ?
|
||||
`
|
||||
|
||||
var hasPermission bool
|
||||
err := s.db.Get(&hasPermission, query, userID, permission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(hasPermission)
|
||||
|
||||
// 根据权限检查结果返回相应错误
|
||||
if !hasPermission {
|
||||
return fmt.Errorf("user %d does not have permission %s", userID, permission)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsSuperAdmin 检查是否为超级管理员
|
||||
func (s *MService) IsSuperAdmin(userID int) bool {
|
||||
return userID == 1
|
||||
}
|
||||
Reference in New Issue
Block a user