CreateSession 创建会话
(userID, ipAddress, userAgent string)
| 854 | |
| 855 | // CreateSession 创建会话 |
| 856 | func (ac *AccessController) CreateSession(userID, ipAddress, userAgent string) (*Session, error) { |
| 857 | ac.mu.Lock() |
| 858 | defer ac.mu.Unlock() |
| 859 | |
| 860 | user, exists := ac.users[userID] |
| 861 | if !exists { |
| 862 | return nil, fmt.Errorf("user %s not found", userID) |
| 863 | } |
| 864 | |
| 865 | if !user.Enabled || user.Status != UserStatusActive { |
| 866 | return nil, fmt.Errorf("user %s is not active", userID) |
| 867 | } |
| 868 | |
| 869 | // 检查会话数量限制 |
| 870 | if ac.config.MaxSessionsPerUser > 0 { |
| 871 | activeSessions := 0 |
| 872 | for _, session := range ac.sessions { |
| 873 | if session.UserID == userID && session.Status == SessionStatusActive { |
| 874 | activeSessions++ |
| 875 | } |
| 876 | } |
| 877 | if activeSessions >= ac.config.MaxSessionsPerUser { |
| 878 | return nil, fmt.Errorf("user %s has reached maximum sessions limit", userID) |
| 879 | } |
| 880 | } |
| 881 | |
| 882 | sessionID := ac.generateSessionID(userID, ipAddress, userAgent) |
| 883 | expiresAt := time.Now().Add(ac.config.SessionTimeout) |
| 884 | |
| 885 | session := &Session{ |
| 886 | ID: sessionID, |
| 887 | UserID: userID, |
| 888 | Username: user.Username, |
| 889 | Roles: user.Roles, |
| 890 | Permissions: ac.getUserPermissions(userID), |
| 891 | IPAddress: ipAddress, |
| 892 | UserAgent: userAgent, |
| 893 | Status: SessionStatusActive, |
| 894 | CreatedAt: time.Now(), |
| 895 | LastActivity: time.Now(), |
| 896 | ExpiresAt: expiresAt, |
| 897 | } |
| 898 | |
| 899 | ac.sessions[sessionID] = session |
| 900 | |
| 901 | // 更新用户最后登录时间 |
| 902 | now := time.Now() |
| 903 | user.LastLogin = &now |
| 904 | user.UpdatedAt = now |
| 905 | |
| 906 | // 记录审计日志 |
| 907 | if ac.config.EnableAudit && ac.auditLog != nil { |
| 908 | _ = ac.auditLog.LogEvent(AuditEvent{ |
| 909 | Type: AuditTypeSessionCreated, |
| 910 | UserID: userID, |
| 911 | Timestamp: time.Now(), |
| 912 | Message: fmt.Sprintf("Session %s created for user %s", sessionID, user.Username), |
| 913 | Metadata: map[string]any{ |
nothing calls this directly
no test coverage detected