邀请
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/perfect-panel/server/internal/model/auth"
|
||||
"github.com/perfect-panel/server/internal/model/coupon"
|
||||
"github.com/perfect-panel/server/internal/model/document"
|
||||
iapapple "github.com/perfect-panel/server/internal/model/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
logmessage "github.com/perfect-panel/server/internal/model/logmessage"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
@@ -27,7 +28,6 @@ import (
|
||||
"github.com/perfect-panel/server/internal/model/ticket"
|
||||
"github.com/perfect-panel/server/internal/model/traffic"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
iapapple "github.com/perfect-panel/server/internal/model/iap/apple"
|
||||
"github.com/perfect-panel/server/pkg/limit"
|
||||
"github.com/perfect-panel/server/pkg/nodeMultiplier"
|
||||
"github.com/perfect-panel/server/pkg/orm"
|
||||
@@ -56,13 +56,13 @@ type ServiceContext struct {
|
||||
ClientModel client.Model
|
||||
TicketModel ticket.Model
|
||||
//ServerModel server.Model
|
||||
SystemModel system.Model
|
||||
CouponModel coupon.Model
|
||||
PaymentModel payment.Model
|
||||
DocumentModel document.Model
|
||||
SubscribeModel subscribe.Model
|
||||
TrafficLogModel traffic.Model
|
||||
AnnouncementModel announcement.Model
|
||||
SystemModel system.Model
|
||||
CouponModel coupon.Model
|
||||
PaymentModel payment.Model
|
||||
DocumentModel document.Model
|
||||
SubscribeModel subscribe.Model
|
||||
TrafficLogModel traffic.Model
|
||||
AnnouncementModel announcement.Model
|
||||
IAPAppleTransactionModel iapapple.Model
|
||||
|
||||
Restart func() error
|
||||
@@ -126,6 +126,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
}
|
||||
|
||||
func (srv *ServiceContext) SessionLimit() int64 {
|
||||
// check custom data
|
||||
cd := srv.Config.Site.CustomData
|
||||
if cd != "" {
|
||||
var obj map[string]interface{}
|
||||
@@ -134,10 +135,12 @@ func (srv *ServiceContext) SessionLimit() int64 {
|
||||
switch val := v.(type) {
|
||||
case float64:
|
||||
if val > 0 {
|
||||
fmt.Printf("[SessionLimit] Using CustomData deviceLimit: %d\n", int64(val))
|
||||
return int64(val)
|
||||
}
|
||||
case string:
|
||||
if n, err := strconv.ParseInt(strings.TrimSpace(val), 10, 64); err == nil && n > 0 {
|
||||
fmt.Printf("[SessionLimit] Using CustomData deviceLimit: %d\n", n)
|
||||
return n
|
||||
}
|
||||
}
|
||||
@@ -146,16 +149,19 @@ func (srv *ServiceContext) SessionLimit() int64 {
|
||||
switch val := v.(type) {
|
||||
case float64:
|
||||
if val > 0 {
|
||||
fmt.Printf("[SessionLimit] Using CustomData DeviceLimit: %d\n", int64(val))
|
||||
return int64(val)
|
||||
}
|
||||
case string:
|
||||
if n, err := strconv.ParseInt(strings.TrimSpace(val), 10, 64); err == nil && n > 0 {
|
||||
fmt.Printf("[SessionLimit] Using CustomData DeviceLimit: %d\n", n)
|
||||
return n
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("[SessionLimit] Using Config MaxSessionsPerUser: %d\n", srv.Config.JwtAuth.MaxSessionsPerUser)
|
||||
return srv.Config.JwtAuth.MaxSessionsPerUser
|
||||
}
|
||||
|
||||
@@ -173,6 +179,22 @@ func (srv *ServiceContext) EnforceUserSessionLimit(ctx context.Context, userId i
|
||||
return err
|
||||
}
|
||||
if count > max {
|
||||
// [SessionDebug] Log all current sessions before eviction
|
||||
// Fetch all sessions (oldest to newest)
|
||||
sessions, _ := srv.Redis.ZRange(ctx, sessionsKey, 0, -1).Result()
|
||||
fmt.Printf("[SessionMonitor] ⚠️ Session Limit Exceeded (Count: %d, Max: %d). User %d has the following active sessions:\n", count, max, userId)
|
||||
|
||||
for i, sid := range sessions {
|
||||
detailKey := fmt.Sprintf("%s:detail:%s", config.SessionIdKey, sid)
|
||||
val, err := srv.Redis.Get(ctx, detailKey).Result()
|
||||
if err == nil {
|
||||
fmt.Printf(" [%d] SessionID: %s | Detail: %s\n", i+1, sid, val)
|
||||
} else {
|
||||
fmt.Printf(" [%d] SessionID: %s | (No Detail - Likely old session)\n", i+1, sid)
|
||||
}
|
||||
}
|
||||
|
||||
// Log before eviction
|
||||
popped, err := srv.Redis.ZPopMin(ctx, sessionsKey, count-max).Result()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -180,6 +202,12 @@ func (srv *ServiceContext) EnforceUserSessionLimit(ctx context.Context, userId i
|
||||
for _, z := range popped {
|
||||
sid := fmt.Sprintf("%v", z.Member)
|
||||
_ = srv.Redis.Del(ctx, fmt.Sprintf("%v:%v", config.SessionIdKey, sid)).Err()
|
||||
// Also delete detail
|
||||
_ = srv.Redis.Del(ctx, fmt.Sprintf("%s:detail:%s", config.SessionIdKey, sid)).Err()
|
||||
|
||||
// 记录被踢出的 Session 信息
|
||||
fmt.Printf("[SessionMonitor] ❌ KICKED OUT Session: user_id=%d session_id=%s reason=exceed_limit\n",
|
||||
userId, sid)
|
||||
}
|
||||
}
|
||||
_ = srv.Redis.Expire(ctx, sessionsKey, time.Duration(srv.Config.JwtAuth.AccessExpire)*time.Second).Err()
|
||||
|
||||
Reference in New Issue
Block a user