Merge branch 'main' of http://1.117.67.95:3000/team/hyapi-server
This commit is contained in:
@@ -6,6 +6,9 @@ import (
|
||||
"time"
|
||||
|
||||
"hyapi-server/internal/config"
|
||||
securityEntities "hyapi-server/internal/domains/security/entities"
|
||||
securityServices "hyapi-server/internal/domains/security/services"
|
||||
user_repositories "hyapi-server/internal/domains/user/repositories"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
@@ -14,15 +17,24 @@ import (
|
||||
|
||||
// JWTAuthMiddleware JWT认证中间件
|
||||
type JWTAuthMiddleware struct {
|
||||
config *config.Config
|
||||
logger *zap.Logger
|
||||
config *config.Config
|
||||
logger *zap.Logger
|
||||
userRepo user_repositories.UserRepository
|
||||
blacklist *securityServices.BlacklistService
|
||||
}
|
||||
|
||||
// NewJWTAuthMiddleware 创建JWT认证中间件
|
||||
func NewJWTAuthMiddleware(cfg *config.Config, logger *zap.Logger) *JWTAuthMiddleware {
|
||||
func NewJWTAuthMiddleware(
|
||||
cfg *config.Config,
|
||||
logger *zap.Logger,
|
||||
userRepo user_repositories.UserRepository,
|
||||
blacklist *securityServices.BlacklistService,
|
||||
) *JWTAuthMiddleware {
|
||||
return &JWTAuthMiddleware{
|
||||
config: cfg,
|
||||
logger: logger,
|
||||
config: cfg,
|
||||
logger: logger,
|
||||
userRepo: userRepo,
|
||||
blacklist: blacklist,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +87,10 @@ func (m *JWTAuthMiddleware) Handle() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
if !m.ensureUserAllowed(c, claims.UserID) {
|
||||
return
|
||||
}
|
||||
|
||||
// 将用户信息添加到上下文
|
||||
c.Set("user_id", claims.UserID)
|
||||
c.Set("username", claims.Username)
|
||||
@@ -124,6 +140,52 @@ func (m *JWTAuthMiddleware) validateToken(tokenString string) (*JWTClaims, error
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
// ensureUserAllowed 复查用户是否仍可访问(黑名单即时生效)
|
||||
func (m *JWTAuthMiddleware) ensureUserAllowed(c *gin.Context, userID string) bool {
|
||||
if m.userRepo == nil || userID == "" {
|
||||
return true
|
||||
}
|
||||
user, err := m.userRepo.GetByID(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
m.logger.Warn("查询用户状态失败", zap.String("user_id", userID), zap.Error(err))
|
||||
m.respondUnauthorized(c, "用户状态无效")
|
||||
return false
|
||||
}
|
||||
if user.IsOnBlacklist() {
|
||||
if m.blacklist != nil {
|
||||
m.blacklist.RecordHit(&securityEntities.BlacklistHitRecord{
|
||||
HitType: securityEntities.HitTypeUserJWT,
|
||||
UserID: userID,
|
||||
Phone: user.Phone,
|
||||
IP: c.ClientIP(),
|
||||
Path: c.Request.URL.Path,
|
||||
Method: c.Request.Method,
|
||||
Reason: user.BlacklistReason,
|
||||
UserAgent: c.GetHeader("User-Agent"),
|
||||
})
|
||||
}
|
||||
m.respondForbidden(c, "账号已被列入黑名单")
|
||||
return false
|
||||
}
|
||||
if !user.CanLogin() {
|
||||
m.respondForbidden(c, "账号不可用")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// respondForbidden 禁止访问
|
||||
func (m *JWTAuthMiddleware) respondForbidden(c *gin.Context, message string) {
|
||||
c.JSON(http.StatusForbidden, gin.H{
|
||||
"success": false,
|
||||
"message": "访问被拒绝",
|
||||
"error": message,
|
||||
"request_id": c.GetString("request_id"),
|
||||
"timestamp": time.Now().Unix(),
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
// respondUnauthorized 返回未授权响应
|
||||
func (m *JWTAuthMiddleware) respondUnauthorized(c *gin.Context, message string) {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
@@ -331,6 +393,10 @@ func (m *AdminAuthMiddleware) Handle() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
if !m.jwtAuth.ensureUserAllowed(c, claims.UserID) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户类型是否为管理员
|
||||
if claims.UserType != "admin" {
|
||||
m.respondForbidden(c, "需要管理员权限")
|
||||
|
||||
66
internal/shared/middleware/managed_ip_blacklist.go
Normal file
66
internal/shared/middleware/managed_ip_blacklist.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
securityEntities "hyapi-server/internal/domains/security/entities"
|
||||
securityServices "hyapi-server/internal/domains/security/services"
|
||||
"hyapi-server/internal/shared/interfaces"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// ManagedIPBlacklistMiddleware 管理端维护的 IP 黑名单拦截
|
||||
type ManagedIPBlacklistMiddleware struct {
|
||||
blacklist *securityServices.BlacklistService
|
||||
response interfaces.ResponseBuilder
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewManagedIPBlacklistMiddleware(
|
||||
blacklist *securityServices.BlacklistService,
|
||||
response interfaces.ResponseBuilder,
|
||||
logger *zap.Logger,
|
||||
) *ManagedIPBlacklistMiddleware {
|
||||
return &ManagedIPBlacklistMiddleware{
|
||||
blacklist: blacklist,
|
||||
response: response,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ManagedIPBlacklistMiddleware) GetName() string { return "managed_ip_blacklist" }
|
||||
func (m *ManagedIPBlacklistMiddleware) GetPriority() int { return 25 }
|
||||
func (m *ManagedIPBlacklistMiddleware) IsGlobal() bool { return true }
|
||||
|
||||
func (m *ManagedIPBlacklistMiddleware) Handle() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ip := c.ClientIP()
|
||||
blocked, entry := m.blacklist.IsIPBlocked(c.Request.Context(), ip)
|
||||
if !blocked {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
reason := "IP在黑名单中"
|
||||
if entry != nil && entry.Reason != "" {
|
||||
reason = entry.Reason
|
||||
}
|
||||
m.blacklist.RecordHit(&securityEntities.BlacklistHitRecord{
|
||||
HitType: securityEntities.HitTypeIP,
|
||||
IP: ip,
|
||||
Path: c.Request.URL.Path,
|
||||
Method: c.Request.Method,
|
||||
Reason: reason,
|
||||
UserAgent: c.GetHeader("User-Agent"),
|
||||
})
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
|
||||
"success": false,
|
||||
"message": "访问被拒绝",
|
||||
"error": "该IP已被列入黑名单",
|
||||
"request_id": c.GetString("request_id"),
|
||||
"timestamp": time.Now().Unix(),
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user