用户管理与权限系统

# 用户管理与权限系统

# 📖 系统概述

在跨境电商的复杂业务环境中,用户管理与权限系统是整个平台的安全基石。该系统不仅需要管理来自全球不同地区的用户,还要处理多语言、多币种、多时区的复杂场景,同时确保数据安全和隐私合规。

想象一个全球化的电商平台,每天有数百万用户从世界各地访问,他们使用不同的语言、货币和支付方式。系统需要为每个用户提供个性化的体验,同时严格控制访问权限,保护敏感数据。从普通消费者到企业采购员,从客服代表到系统管理员,每个角色都有其特定的权限边界和业务需求。

# 核心功能

  1. 多租户用户管理:支持B2C消费者、B2B企业用户、平台运营人员等多种用户类型
  2. 细粒度权限控制:基于RBAC模型的角色权限管理,支持动态权限分配
  3. 全球化身份认证:支持多种认证方式,包括社交登录、企业SSO、多因素认证
  4. 数据隐私保护:符合GDPR、CCPA等国际隐私法规的数据处理机制
  5. 安全审计追踪:完整的用户行为日志和安全事件监控
  6. 智能风险控制:基于机器学习的异常行为检测和风险评估

# 🏗️ 系统架构设计

graph TB
    subgraph "用户管理与权限系统架构"
        subgraph "接入层"
            A1[Web前端]
            A2[移动端APP]
            A3[API网关]
            A4[第三方集成]
        end
        
        subgraph "认证服务层"
            B1[身份认证服务]
            B2[OAuth2.0服务]
            B3[JWT令牌服务]
            B4[多因素认证]
            B5[社交登录集成]
        end
        
        subgraph "权限管理层"
            C1[RBAC权限引擎]
            C2[动态权限分配]
            C3[资源访问控制]
            C4[权限缓存服务]
        end
        
        subgraph "用户服务层"
            D1[用户注册服务]
            D2[用户资料管理]
            D3[企业用户管理]
            D4[用户分组服务]
            D5[用户偏好设置]
        end
        
        subgraph "安全服务层"
            E1[风险评估引擎]
            E2[行为分析服务]
            E3[安全审计服务]
            E4[数据加密服务]
            E5[隐私合规服务]
        end
        
        subgraph "数据存储层"
            F1[(用户数据库)]
            F2[(权限数据库)]
            F3[(审计日志库)]
            F4[(缓存集群)]
            F5[(文件存储)]
        end
        
        subgraph "外部服务"
            G1[邮件服务]
            G2[短信服务]
            G3[第三方认证]
            G4[风控服务]
            G5[合规检查]
        end
    end
    
    A1 --> A3
    A2 --> A3
    A4 --> A3
    A3 --> B1
    
    B1 --> B2
    B1 --> B3
    B1 --> B4
    B1 --> B5
    
    B1 --> C1
    C1 --> C2
    C1 --> C3
    C1 --> C4
    
    B1 --> D1
    D1 --> D2
    D1 --> D3
    D1 --> D4
    D1 --> D5
    
    C1 --> E1
    E1 --> E2
    E1 --> E3
    E1 --> E4
    E1 --> E5
    
    D1 --> F1
    C1 --> F2
    E3 --> F3
    C4 --> F4
    D2 --> F5
    
    B4 --> G1
    B4 --> G2
    B5 --> G3
    E1 --> G4
    E5 --> G5

# 💻 核心代码实现

# 1. 用户实体模型

@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false)
    private String username;
    
    @Column(unique = true, nullable = false)
    private String email;
    
    @Column(nullable = false)
    private String passwordHash;
    
    @Column(name = "phone_number")
    private String phoneNumber;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private UserType userType;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private UserStatus status;
    
    @Column(name = "first_name")
    private String firstName;
    
    @Column(name = "last_name")
    private String lastName;
    
    @Column(name = "display_name")
    private String displayName;
    
    @Column(name = "avatar_url")
    private String avatarUrl;
    
    @Column(name = "preferred_language")
    private String preferredLanguage;
    
    @Column(name = "preferred_currency")
    private String preferredCurrency;
    
    @Column(name = "time_zone")
    private String timeZone;
    
    @Column(name = "country_code")
    private String countryCode;
    
    @Column(name = "region_code")
    private String regionCode;
    
    @Column(name = "date_of_birth")
    private LocalDate dateOfBirth;
    
    @Enumerated(EnumType.STRING)
    private Gender gender;
    
    @Column(name = "email_verified")
    private Boolean emailVerified = false;
    
    @Column(name = "phone_verified")
    private Boolean phoneVerified = false;
    
    @Column(name = "two_factor_enabled")
    private Boolean twoFactorEnabled = false;
    
    @Column(name = "last_login_at")
    private LocalDateTime lastLoginAt;
    
    @Column(name = "last_login_ip")
    private String lastLoginIp;
    
    @Column(name = "login_attempts")
    private Integer loginAttempts = 0;
    
    @Column(name = "locked_until")
    private LocalDateTime lockedUntil;
    
    @Column(name = "password_changed_at")
    private LocalDateTime passwordChangedAt;
    
    @Column(name = "terms_accepted_at")
    private LocalDateTime termsAcceptedAt;
    
    @Column(name = "privacy_policy_accepted_at")
    private LocalDateTime privacyPolicyAcceptedAt;
    
    @Column(name = "marketing_consent")
    private Boolean marketingConsent = false;
    
    @Column(name = "data_processing_consent")
    private Boolean dataProcessingConsent = false;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    @Column(name = "deleted_at")
    private LocalDateTime deletedAt;
    
    // 用户角色关联
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles = new HashSet<>();
    
    // 用户组关联
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "user_groups",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "group_id")
    )
    private Set<UserGroup> groups = new HashSet<>();
    
    // 用户属性扩展
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<UserAttribute> attributes = new HashSet<>();
    
    // 社交账号关联
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<SocialAccount> socialAccounts = new HashSet<>();
    
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
    
    /**
     * 检查用户是否被锁定
     */
    public boolean isLocked() {
        return lockedUntil != null && lockedUntil.isAfter(LocalDateTime.now());
    }
    
    /**
     * 检查用户是否激活
     */
    public boolean isActive() {
        return status == UserStatus.ACTIVE && !isLocked();
    }
    
    /**
     * 检查用户是否有指定权限
     */
    public boolean hasPermission(String permission) {
        return roles.stream()
                .flatMap(role -> role.getPermissions().stream())
                .anyMatch(perm -> perm.getName().equals(permission));
    }
    
    /**
     * 检查用户是否有指定角色
     */
    public boolean hasRole(String roleName) {
        return roles.stream()
                .anyMatch(role -> role.getName().equals(roleName));
    }
    
    /**
     * 获取用户完整显示名称
     */
    public String getFullDisplayName() {
        if (displayName != null && !displayName.trim().isEmpty()) {
            return displayName;
        }
        
        if (firstName != null && lastName != null) {
            return firstName + " " + lastName;
        }
        
        return username;
    }
    
    /**
     * 增加登录失败次数
     */
    public void incrementLoginAttempts() {
        this.loginAttempts = (this.loginAttempts == null ? 0 : this.loginAttempts) + 1;
    }
    
    /**
     * 重置登录失败次数
     */
    public void resetLoginAttempts() {
        this.loginAttempts = 0;
        this.lockedUntil = null;
    }
    
    /**
     * 锁定用户账户
     */
    public void lockAccount(Duration lockDuration) {
        this.lockedUntil = LocalDateTime.now().plus(lockDuration);
    }
    
    // 其他业务方法省略...
}

// 用户类型枚举
public enum UserType {
    CONSUMER,           // 普通消费者
    BUSINESS,           // 企业用户
    ADMIN,              // 平台管理员
    CUSTOMER_SERVICE,   // 客服代表
    MERCHANT,           // 商家用户
    SUPPLIER,           // 供应商
    AFFILIATE           // 联盟伙伴
}

// 用户状态枚举
public enum UserStatus {
    PENDING,            // 待激活
    ACTIVE,             // 活跃
    INACTIVE,           // 非活跃
    SUSPENDED,          // 暂停
    BANNED,             // 禁用
    DELETED             // 已删除
}

// 性别枚举
public enum Gender {
    MALE,
    FEMALE,
    OTHER,
    PREFER_NOT_TO_SAY
}

# 2. 角色权限模型

@Entity
@Table(name = "roles")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Role {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false)
    private String name;
    
    @Column(name = "display_name")
    private String displayName;
    
    private String description;
    
    @Enumerated(EnumType.STRING)
    private RoleType type;
    
    @Column(name = "is_system_role")
    private Boolean isSystemRole = false;
    
    @Column(name = "is_active")
    private Boolean isActive = true;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    // 角色权限关联
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "role_permissions",
        joinColumns = @JoinColumn(name = "role_id"),
        inverseJoinColumns = @JoinColumn(name = "permission_id")
    )
    private Set<Permission> permissions = new HashSet<>();
    
    // 角色层级关系
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_role_id")
    private Role parentRole;
    
    @OneToMany(mappedBy = "parentRole", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Role> childRoles = new HashSet<>();
    
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
    
    /**
     * 获取所有权限(包括继承的权限)
     */
    public Set<Permission> getAllPermissions() {
        Set<Permission> allPermissions = new HashSet<>(permissions);
        
        // 递归获取父角色权限
        if (parentRole != null) {
            allPermissions.addAll(parentRole.getAllPermissions());
        }
        
        return allPermissions;
    }
    
    /**
     * 检查是否有指定权限
     */
    public boolean hasPermission(String permissionName) {
        return getAllPermissions().stream()
                .anyMatch(permission -> permission.getName().equals(permissionName));
    }
}

@Entity
@Table(name = "permissions")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Permission {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false)
    private String name;
    
    @Column(name = "display_name")
    private String displayName;
    
    private String description;
    
    @Column(name = "resource_type")
    private String resourceType;
    
    @Column(name = "action_type")
    private String actionType;
    
    @Enumerated(EnumType.STRING)
    private PermissionScope scope;
    
    @Column(name = "is_system_permission")
    private Boolean isSystemPermission = false;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    // 权限分组
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "permission_group_id")
    private PermissionGroup permissionGroup;
    
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
}

// 角色类型枚举
public enum RoleType {
    SYSTEM,             // 系统角色
    BUSINESS,           // 业务角色
    CUSTOM              // 自定义角色
}

// 权限范围枚举
public enum PermissionScope {
    GLOBAL,             // 全局权限
    ORGANIZATION,       // 组织权限
    DEPARTMENT,         // 部门权限
    PERSONAL            // 个人权限
}

# 3. 用户认证服务

@Service
@Slf4j
public class UserAuthenticationService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
    private JwtTokenService jwtTokenService;
    
    @Autowired
    private TwoFactorAuthService twoFactorAuthService;
    
    @Autowired
    private UserSecurityService userSecurityService;
    
    @Autowired
    private AuditLogService auditLogService;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    private static final int MAX_LOGIN_ATTEMPTS = 5;
    private static final Duration ACCOUNT_LOCK_DURATION = Duration.ofMinutes(30);
    
    /**
     * 用户登录认证
     */
    @Transactional
    public AuthenticationResult authenticate(LoginRequest request) {
        String identifier = request.getIdentifier(); // 可以是用户名、邮箱或手机号
        String password = request.getPassword();
        String clientIp = request.getClientIp();
        String userAgent = request.getUserAgent();
        
        // 查找用户
        User user = findUserByIdentifier(identifier);
        if (user == null) {
            auditLogService.logFailedLogin(identifier, clientIp, "用户不存在");
            throw new AuthenticationException("用户名或密码错误");
        }
        
        // 检查账户状态
        validateAccountStatus(user);
        
        // 检查账户是否被锁定
        if (user.isLocked()) {
            auditLogService.logFailedLogin(identifier, clientIp, "账户被锁定");
            throw new AccountLockedException("账户已被锁定,请稍后再试");
        }
        
        // 验证密码
        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            handleFailedLogin(user, clientIp);
            throw new AuthenticationException("用户名或密码错误");
        }
        
        // 检查是否需要二次认证
        if (user.getTwoFactorEnabled()) {
            return handleTwoFactorAuthentication(user, request);
        }
        
        // 登录成功处理
        return handleSuccessfulLogin(user, clientIp, userAgent);
    }
    
    /**
     * 二次认证处理
     */
    private AuthenticationResult handleTwoFactorAuthentication(User user, LoginRequest request) {
        String twoFactorCode = request.getTwoFactorCode();
        
        if (twoFactorCode == null || twoFactorCode.trim().isEmpty()) {
            // 发送二次认证码
            twoFactorAuthService.sendTwoFactorCode(user);
            
            return AuthenticationResult.builder()
                    .success(false)
                    .requiresTwoFactor(true)
                    .userId(user.getId())
                    .message("请输入二次认证码")
                    .build();
        }
        
        // 验证二次认证码
        if (!twoFactorAuthService.verifyTwoFactorCode(user, twoFactorCode)) {
            auditLogService.logFailedTwoFactorAuth(user.getId(), request.getClientIp());
            throw new TwoFactorAuthException("二次认证码错误");
        }
        
        // 二次认证成功
        return handleSuccessfulLogin(user, request.getClientIp(), request.getUserAgent());
    }
    
    /**
     * 登录成功处理
     */
    private AuthenticationResult handleSuccessfulLogin(User user, String clientIp, String userAgent) {
        // 重置登录失败次数
        user.resetLoginAttempts();
        user.setLastLoginAt(LocalDateTime.now());
        user.setLastLoginIp(clientIp);
        userRepository.save(user);
        
        // 生成JWT令牌
        String accessToken = jwtTokenService.generateAccessToken(user);
        String refreshToken = jwtTokenService.generateRefreshToken(user);
        
        // 缓存用户会话信息
        cacheUserSession(user, accessToken, clientIp, userAgent);
        
        // 记录登录日志
        auditLogService.logSuccessfulLogin(user.getId(), clientIp, userAgent);
        
        // 异步执行安全检查
        userSecurityService.performSecurityCheck(user, clientIp, userAgent);
        
        return AuthenticationResult.builder()
                .success(true)
                .userId(user.getId())
                .username(user.getUsername())
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .expiresIn(jwtTokenService.getAccessTokenExpiration())
                .userType(user.getUserType())
                .roles(user.getRoles().stream()
                        .map(Role::getName)
                        .collect(Collectors.toSet()))
                .permissions(user.getRoles().stream()
                        .flatMap(role -> role.getAllPermissions().stream())
                        .map(Permission::getName)
                        .collect(Collectors.toSet()))
                .build();
    }
    
    /**
     * 登录失败处理
     */
    private void handleFailedLogin(User user, String clientIp) {
        user.incrementLoginAttempts();
        
        if (user.getLoginAttempts() >= MAX_LOGIN_ATTEMPTS) {
            user.lockAccount(ACCOUNT_LOCK_DURATION);
            auditLogService.logAccountLocked(user.getId(), clientIp);
            log.warn("用户账户被锁定 - 用户ID: {}, IP: {}", user.getId(), clientIp);
        }
        
        userRepository.save(user);
        auditLogService.logFailedLogin(user.getUsername(), clientIp, "密码错误");
    }
    
    /**
     * 根据标识符查找用户
     */
    private User findUserByIdentifier(String identifier) {
        // 尝试按用户名查找
        Optional<User> user = userRepository.findByUsername(identifier);
        if (user.isPresent()) {
            return user.get();
        }
        
        // 尝试按邮箱查找
        if (identifier.contains("@")) {
            user = userRepository.findByEmail(identifier);
            if (user.isPresent()) {
                return user.get();
            }
        }
        
        // 尝试按手机号查找
        if (identifier.matches("\\+?[0-9\\s-()]+")) {
            user = userRepository.findByPhoneNumber(identifier);
            if (user.isPresent()) {
                return user.get();
            }
        }
        
        return null;
    }
    
    /**
     * 验证账户状态
     */
    private void validateAccountStatus(User user) {
        switch (user.getStatus()) {
            case PENDING:
                throw new AccountNotActivatedException("账户尚未激活,请检查邮箱激活链接");
            case INACTIVE:
                throw new AccountInactiveException("账户已停用,请联系客服");
            case SUSPENDED:
                throw new AccountSuspendedException("账户已暂停,请联系客服");
            case BANNED:
                throw new AccountBannedException("账户已被禁用");
            case DELETED:
                throw new AccountDeletedException("账户已被删除");
            case ACTIVE:
                // 账户正常,继续处理
                break;
            default:
                throw new AuthenticationException("账户状态异常");
        }
    }
    
    /**
     * 缓存用户会话信息
     */
    private void cacheUserSession(User user, String accessToken, String clientIp, String userAgent) {
        UserSession session = UserSession.builder()
                .userId(user.getId())
                .username(user.getUsername())
                .accessToken(accessToken)
                .clientIp(clientIp)
                .userAgent(userAgent)
                .loginTime(LocalDateTime.now())
                .lastAccessTime(LocalDateTime.now())
                .build();
        
        String sessionKey = "user:session:" + user.getId() + ":" + accessToken.substring(0, 8);
        redisTemplate.opsForValue().set(sessionKey, session, 
                Duration.ofSeconds(jwtTokenService.getAccessTokenExpiration()));
    }
    
    /**
     * 刷新访问令牌
     */
    public TokenRefreshResult refreshToken(String refreshToken) {
        if (!jwtTokenService.validateRefreshToken(refreshToken)) {
            throw new InvalidTokenException("刷新令牌无效或已过期");
        }
        
        Long userId = jwtTokenService.getUserIdFromRefreshToken(refreshToken);
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        // 检查用户状态
        if (!user.isActive()) {
            throw new AuthenticationException("用户账户异常");
        }
        
        // 生成新的访问令牌
        String newAccessToken = jwtTokenService.generateAccessToken(user);
        
        return TokenRefreshResult.builder()
                .accessToken(newAccessToken)
                .expiresIn(jwtTokenService.getAccessTokenExpiration())
                .build();
    }
    
    /**
     * 用户登出
     */
    public void logout(String accessToken) {
        // 将令牌加入黑名单
        jwtTokenService.blacklistToken(accessToken);
        
        // 清除会话缓存
        Long userId = jwtTokenService.getUserIdFromAccessToken(accessToken);
        String sessionKey = "user:session:" + userId + ":" + accessToken.substring(0, 8);
        redisTemplate.delete(sessionKey);
        
        // 记录登出日志
        auditLogService.logLogout(userId);
    }
    
    // 其他认证相关方法省略...
}

### 4. 权限管理服务

```java
@Service
@Slf4j
public class PermissionManagementService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private RoleRepository roleRepository;
    
    @Autowired
    private PermissionRepository permissionRepository;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private AuditLogService auditLogService;
    
    private static final String PERMISSION_CACHE_PREFIX = "permission:user:";
    private static final Duration PERMISSION_CACHE_TTL = Duration.ofMinutes(30);
    
    /**
     * 检查用户权限
     */
    public boolean hasPermission(Long userId, String permission) {
        // 先从缓存获取
        Set<String> cachedPermissions = getCachedUserPermissions(userId);
        if (cachedPermissions != null) {
            return cachedPermissions.contains(permission);
        }
        
        // 从数据库获取并缓存
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        Set<String> userPermissions = getUserPermissions(user);
        cacheUserPermissions(userId, userPermissions);
        
        return userPermissions.contains(permission);
    }
    
    /**
     * 检查用户是否有指定角色
     */
    public boolean hasRole(Long userId, String roleName) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        return user.getRoles().stream()
                .anyMatch(role -> role.getName().equals(roleName));
    }
    
    /**
     * 获取用户所有权限
     */
    public Set<String> getUserPermissions(User user) {
        Set<String> permissions = new HashSet<>();
        
        // 从角色获取权限
        for (Role role : user.getRoles()) {
            if (role.getIsActive()) {
                permissions.addAll(role.getAllPermissions().stream()
                        .map(Permission::getName)
                        .collect(Collectors.toSet()));
            }
        }
        
        // 从用户组获取权限
        for (UserGroup group : user.getGroups()) {
            if (group.getIsActive()) {
                permissions.addAll(group.getPermissions().stream()
                        .map(Permission::getName)
                        .collect(Collectors.toSet()));
            }
        }
        
        return permissions;
    }
    
    /**
     * 为用户分配角色
     */
    @Transactional
    public void assignRoleToUser(Long userId, Long roleId, Long operatorId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new RoleNotFoundException("角色不存在"));
        
        if (!role.getIsActive()) {
            throw new RoleInactiveException("角色已停用");
        }
        
        // 检查是否已有该角色
        if (user.getRoles().contains(role)) {
            throw new RoleAlreadyAssignedException("用户已拥有该角色");
        }
        
        user.getRoles().add(role);
        userRepository.save(user);
        
        // 清除权限缓存
        clearUserPermissionCache(userId);
        
        // 记录审计日志
        auditLogService.logRoleAssignment(userId, roleId, operatorId);
        
        log.info("为用户分配角色 - 用户ID: {}, 角色ID: {}, 操作员ID: {}", 
                userId, roleId, operatorId);
    }
    
    /**
     * 移除用户角色
     */
    @Transactional
    public void removeRoleFromUser(Long userId, Long roleId, Long operatorId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new RoleNotFoundException("角色不存在"));
        
        if (!user.getRoles().contains(role)) {
            throw new RoleNotAssignedException("用户未拥有该角色");
        }
        
        user.getRoles().remove(role);
        userRepository.save(user);
        
        // 清除权限缓存
        clearUserPermissionCache(userId);
        
        // 记录审计日志
        auditLogService.logRoleRemoval(userId, roleId, operatorId);
        
        log.info("移除用户角色 - 用户ID: {}, 角色ID: {}, 操作员ID: {}", 
                userId, roleId, operatorId);
    }
    
    /**
     * 创建自定义角色
     */
    @Transactional
    public Role createCustomRole(CreateRoleRequest request, Long operatorId) {
        // 检查角色名是否已存在
        if (roleRepository.existsByName(request.getName())) {
            throw new RoleAlreadyExistsException("角色名已存在");
        }
        
        Role role = Role.builder()
                .name(request.getName())
                .displayName(request.getDisplayName())
                .description(request.getDescription())
                .type(RoleType.CUSTOM)
                .isSystemRole(false)
                .isActive(true)
                .build();
        
        role = roleRepository.save(role);
        
        // 分配权限
        if (request.getPermissionIds() != null && !request.getPermissionIds().isEmpty()) {
            assignPermissionsToRole(role.getId(), request.getPermissionIds(), operatorId);
        }
        
        // 记录审计日志
        auditLogService.logRoleCreation(role.getId(), operatorId);
        
        log.info("创建自定义角色 - 角色ID: {}, 角色名: {}, 操作员ID: {}", 
                role.getId(), role.getName(), operatorId);
        
        return role;
    }
    
    /**
     * 为角色分配权限
     */
    @Transactional
    public void assignPermissionsToRole(Long roleId, Set<Long> permissionIds, Long operatorId) {
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new RoleNotFoundException("角色不存在"));
        
        if (role.getIsSystemRole()) {
            throw new SystemRoleModificationException("不能修改系统角色");
        }
        
        Set<Permission> permissions = permissionRepository.findAllById(permissionIds)
                .stream().collect(Collectors.toSet());
        
        if (permissions.size() != permissionIds.size()) {
            throw new PermissionNotFoundException("部分权限不存在");
        }
        
        role.setPermissions(permissions);
        roleRepository.save(role);
        
        // 清除相关用户的权限缓存
        clearRoleUsersPermissionCache(roleId);
        
        // 记录审计日志
        auditLogService.logPermissionAssignment(roleId, permissionIds, operatorId);
        
        log.info("为角色分配权限 - 角色ID: {}, 权限数量: {}, 操作员ID: {}", 
                roleId, permissions.size(), operatorId);
    }
    
    /**
     * 动态权限检查(支持资源级权限)
     */
    public boolean hasResourcePermission(Long userId, String resource, String action, String resourceId) {
        // 构建完整权限字符串
        String fullPermission = String.format("%s:%s", resource, action);
        
        // 检查基础权限
        if (!hasPermission(userId, fullPermission)) {
            return false;
        }
        
        // 检查资源级权限
        return checkResourceLevelPermission(userId, resource, action, resourceId);
    }
    
    /**
     * 检查资源级权限
     */
    private boolean checkResourceLevelPermission(Long userId, String resource, String action, String resourceId) {
        // 获取用户的资源权限配置
        List<ResourcePermission> resourcePermissions = getResourcePermissions(userId, resource);
        
        if (resourcePermissions.isEmpty()) {
            // 如果没有特定资源权限配置,则允许访问(基于基础权限)
            return true;
        }
        
        // 检查是否有对特定资源的权限
        return resourcePermissions.stream()
                .anyMatch(rp -> rp.getResourceId().equals(resourceId) && 
                               rp.getActions().contains(action));
    }
    
    /**
     * 获取用户的资源权限
     */
    private List<ResourcePermission> getResourcePermissions(Long userId, String resource) {
        // 这里可以从数据库或缓存中获取用户的资源级权限配置
        // 简化实现,实际项目中需要根据具体需求设计
        return Collections.emptyList();
    }
    
    /**
     * 缓存用户权限
     */
    private void cacheUserPermissions(Long userId, Set<String> permissions) {
        String cacheKey = PERMISSION_CACHE_PREFIX + userId;
        redisTemplate.opsForValue().set(cacheKey, permissions, PERMISSION_CACHE_TTL);
    }
    
    /**
     * 获取缓存的用户权限
     */
    @SuppressWarnings("unchecked")
    private Set<String> getCachedUserPermissions(Long userId) {
        String cacheKey = PERMISSION_CACHE_PREFIX + userId;
        return (Set<String>) redisTemplate.opsForValue().get(cacheKey);
    }
    
    /**
     * 清除用户权限缓存
     */
    private void clearUserPermissionCache(Long userId) {
        String cacheKey = PERMISSION_CACHE_PREFIX + userId;
        redisTemplate.delete(cacheKey);
    }
    
    /**
     * 清除角色相关用户的权限缓存
     */
    private void clearRoleUsersPermissionCache(Long roleId) {
        List<User> roleUsers = userRepository.findByRolesId(roleId);
        for (User user : roleUsers) {
            clearUserPermissionCache(user.getId());
        }
    }
    
    // 其他权限管理方法省略...
}

# 5. 用户注册服务

@Service
@Slf4j
public class UserRegistrationService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private RoleRepository roleRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
    private EmailVerificationService emailVerificationService;
    
    @Autowired
    private SmsVerificationService smsVerificationService;
    
    @Autowired
    private UserValidationService userValidationService;
    
    @Autowired
    private AuditLogService auditLogService;
    
    @Autowired
    private NotificationService notificationService;
    
    /**
     * 用户注册
     */
    @Transactional
    public UserRegistrationResult registerUser(UserRegistrationRequest request) {
        // 验证注册请求
        validateRegistrationRequest(request);
        
        // 检查用户是否已存在
        checkUserExistence(request);
        
        // 创建用户
        User user = createUser(request);
        
        // 分配默认角色
        assignDefaultRole(user, request.getUserType());
        
        // 保存用户
        user = userRepository.save(user);
        
        // 发送验证邮件
        if (request.getEmail() != null) {
            emailVerificationService.sendVerificationEmail(user);
        }
        
        // 发送验证短信
        if (request.getPhoneNumber() != null) {
            smsVerificationService.sendVerificationSms(user);
        }
        
        // 记录注册日志
        auditLogService.logUserRegistration(user.getId(), request.getClientIp());
        
        // 发送欢迎通知
        notificationService.sendWelcomeNotification(user);
        
        log.info("用户注册成功 - 用户ID: {}, 用户名: {}, 邮箱: {}", 
                user.getId(), user.getUsername(), user.getEmail());
        
        return UserRegistrationResult.builder()
                .success(true)
                .userId(user.getId())
                .username(user.getUsername())
                .email(user.getEmail())
                .requiresEmailVerification(!user.getEmailVerified())
                .requiresPhoneVerification(!user.getPhoneVerified())
                .message("注册成功,请查看邮箱验证链接")
                .build();
    }
    
    /**
     * 企业用户注册
     */
    @Transactional
    public UserRegistrationResult registerBusinessUser(BusinessUserRegistrationRequest request) {
        // 验证企业注册请求
        validateBusinessRegistrationRequest(request);
        
        // 检查企业信息
        validateBusinessInformation(request.getBusinessInfo());
        
        // 创建企业用户
        User user = createBusinessUser(request);
        
        // 创建企业信息
        BusinessProfile businessProfile = createBusinessProfile(user, request.getBusinessInfo());
        
        // 分配企业用户角色
        assignBusinessRole(user, request.getBusinessType());
        
        // 保存用户
        user = userRepository.save(user);
        
        // 企业认证流程
        initiateBusinessVerification(user, businessProfile);
        
        // 发送企业注册通知
        notificationService.sendBusinessRegistrationNotification(user, businessProfile);
        
        log.info("企业用户注册成功 - 用户ID: {}, 企业名称: {}", 
                user.getId(), businessProfile.getCompanyName());
        
        return UserRegistrationResult.builder()
                .success(true)
                .userId(user.getId())
                .username(user.getUsername())
                .email(user.getEmail())
                .requiresBusinessVerification(true)
                .message("企业注册成功,请等待企业认证审核")
                .build();
    }
    
    /**
     * 邮箱验证
     */
    @Transactional
    public EmailVerificationResult verifyEmail(String verificationToken) {
        EmailVerification verification = emailVerificationService
                .getVerificationByToken(verificationToken);
        
        if (verification == null) {
            throw new InvalidVerificationTokenException("验证链接无效或已过期");
        }
        
        if (verification.isExpired()) {
            throw new VerificationTokenExpiredException("验证链接已过期");
        }
        
        if (verification.isUsed()) {
            throw new VerificationTokenUsedException("验证链接已使用");
        }
        
        // 更新用户邮箱验证状态
        User user = verification.getUser();
        user.setEmailVerified(true);
        userRepository.save(user);
        
        // 标记验证为已使用
        verification.markAsUsed();
        emailVerificationService.saveVerification(verification);
        
        // 检查是否需要激活账户
        if (user.getStatus() == UserStatus.PENDING && 
            (!requiresPhoneVerification(user) || user.getPhoneVerified())) {
            activateUser(user);
        }
        
        // 记录验证日志
        auditLogService.logEmailVerification(user.getId());
        
        log.info("邮箱验证成功 - 用户ID: {}, 邮箱: {}", user.getId(), user.getEmail());
        
        return EmailVerificationResult.builder()
                .success(true)
                .userId(user.getId())
                .email(user.getEmail())
                .accountActivated(user.getStatus() == UserStatus.ACTIVE)
                .build();
    }
    
    /**
     * 手机号验证
     */
    @Transactional
    public PhoneVerificationResult verifyPhone(PhoneVerificationRequest request) {
        User user = userRepository.findById(request.getUserId())
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        if (!smsVerificationService.verifyCode(user.getPhoneNumber(), request.getVerificationCode())) {
            throw new InvalidVerificationCodeException("验证码错误或已过期");
        }
        
        // 更新用户手机验证状态
        user.setPhoneVerified(true);
        userRepository.save(user);
        
        // 检查是否需要激活账户
        if (user.getStatus() == UserStatus.PENDING && user.getEmailVerified()) {
            activateUser(user);
        }
        
        // 记录验证日志
        auditLogService.logPhoneVerification(user.getId());
        
        log.info("手机验证成功 - 用户ID: {}, 手机号: {}", user.getId(), user.getPhoneNumber());
        
        return PhoneVerificationResult.builder()
                .success(true)
                .userId(user.getId())
                .phoneNumber(user.getPhoneNumber())
                .accountActivated(user.getStatus() == UserStatus.ACTIVE)
                .build();
    }
    
    /**
     * 重新发送验证邮件
     */
    public void resendVerificationEmail(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        if (user.getEmailVerified()) {
            throw new EmailAlreadyVerifiedException("邮箱已验证");
        }
        
        // 检查发送频率限制
        if (emailVerificationService.isRateLimited(user.getEmail())) {
            throw new VerificationRateLimitException("发送过于频繁,请稍后再试");
        }
        
        emailVerificationService.sendVerificationEmail(user);
        
        log.info("重新发送验证邮件 - 用户ID: {}, 邮箱: {}", user.getId(), user.getEmail());
    }
    
    /**
     * 重新发送验证短信
     */
    public void resendVerificationSms(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在"));
        
        if (user.getPhoneVerified()) {
            throw new PhoneAlreadyVerifiedException("手机号已验证");
        }
        
        // 检查发送频率限制
        if (smsVerificationService.isRateLimited(user.getPhoneNumber())) {
            throw new VerificationRateLimitException("发送过于频繁,请稍后再试");
        }
        
        smsVerificationService.sendVerificationSms(user);
        
        log.info("重新发送验证短信 - 用户ID: {}, 手机号: {}", user.getId(), user.getPhoneNumber());
    }
    
    /**
     * 验证注册请求
     */
    private void validateRegistrationRequest(UserRegistrationRequest request) {
        // 用户名验证
        if (!userValidationService.isValidUsername(request.getUsername())) {
            throw new InvalidUsernameException("用户名格式不正确");
        }
        
        // 邮箱验证
        if (request.getEmail() != null && !userValidationService.isValidEmail(request.getEmail())) {
            throw new InvalidEmailException("邮箱格式不正确");
        }
        
        // 手机号验证
        if (request.getPhoneNumber() != null && !userValidationService.isValidPhoneNumber(request.getPhoneNumber())) {
            throw new InvalidPhoneNumberException("手机号格式不正确");
        }
        
        // 密码强度验证
        if (!userValidationService.isStrongPassword(request.getPassword())) {
            throw new WeakPasswordException("密码强度不足");
        }
        
        // 验证必需的同意条款
        if (!request.getTermsAccepted()) {
            throw new TermsNotAcceptedException("必须同意服务条款");
        }
        
        if (!request.getPrivacyPolicyAccepted()) {
            throw new PrivacyPolicyNotAcceptedException("必须同意隐私政策");
        }
    }
    
    /**
     * 检查用户是否已存在
     */
    private void checkUserExistence(UserRegistrationRequest request) {
        // 检查用户名
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new UsernameAlreadyExistsException("用户名已存在");
        }
        
        // 检查邮箱
        if (request.getEmail() != null && userRepository.existsByEmail(request.getEmail())) {
            throw new EmailAlreadyExistsException("邮箱已注册");
        }
        
        // 检查手机号
        if (request.getPhoneNumber() != null && userRepository.existsByPhoneNumber(request.getPhoneNumber())) {
            throw new PhoneNumberAlreadyExistsException("手机号已注册");
        }
    }
    
    /**
     * 创建用户
     */
    private User createUser(UserRegistrationRequest request) {
        return User.builder()
                .username(request.getUsername())
                .email(request.getEmail())
                .phoneNumber(request.getPhoneNumber())
                .passwordHash(passwordEncoder.encode(request.getPassword()))
                .userType(request.getUserType())
                .status(UserStatus.PENDING)
                .firstName(request.getFirstName())
                .lastName(request.getLastName())
                .preferredLanguage(request.getPreferredLanguage())
                .preferredCurrency(request.getPreferredCurrency())
                .timeZone(request.getTimeZone())
                .countryCode(request.getCountryCode())
                .regionCode(request.getRegionCode())
                .dateOfBirth(request.getDateOfBirth())
                .gender(request.getGender())
                .emailVerified(false)
                .phoneVerified(false)
                .twoFactorEnabled(false)
                .termsAcceptedAt(LocalDateTime.now())
                .privacyPolicyAcceptedAt(LocalDateTime.now())
                .marketingConsent(request.getMarketingConsent())
                .dataProcessingConsent(true)
                .passwordChangedAt(LocalDateTime.now())
                .build();
    }
    
    /**
     * 分配默认角色
     */
    private void assignDefaultRole(User user, UserType userType) {
        String defaultRoleName = getDefaultRoleName(userType);
        Role defaultRole = roleRepository.findByName(defaultRoleName)
                .orElseThrow(() -> new RoleNotFoundException("默认角色不存在: " + defaultRoleName));
        
        user.getRoles().add(defaultRole);
    }
    
    /**
     * 获取默认角色名
     */
    private String getDefaultRoleName(UserType userType) {
        switch (userType) {
            case CONSUMER:
                return "ROLE_CONSUMER";
            case BUSINESS:
                return "ROLE_BUSINESS_USER";
            case MERCHANT:
                return "ROLE_MERCHANT";
            case SUPPLIER:
                return "ROLE_SUPPLIER";
            case AFFILIATE:
                return "ROLE_AFFILIATE";
            default:
                return "ROLE_USER";
        }
    }
    
    /**
     * 激活用户账户
     */
    private void activateUser(User user) {
        user.setStatus(UserStatus.ACTIVE);
        userRepository.save(user);
        
        // 发送激活通知
        notificationService.sendAccountActivationNotification(user);
        
        // 记录激活日志
        auditLogService.logAccountActivation(user.getId());
        
        log.info("用户账户已激活 - 用户ID: {}", user.getId());
    }
    
    /**
     * 检查是否需要手机验证
     */
    private boolean requiresPhoneVerification(User user) {
        return user.getPhoneNumber() != null && !user.getPhoneNumber().trim().isEmpty();
    }
    
    // 其他注册相关方法省略...
}

# 6. 安全服务

@Service
@Slf4j
public class SecurityService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private SecurityEventRepository securityEventRepository;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private NotificationService notificationService;
    
    @Autowired
    private GeoLocationService geoLocationService;
    
    @Autowired
    private DeviceFingerprintService deviceFingerprintService;
    
    private static final String LOGIN_ATTEMPT_PREFIX = "login_attempt:";
    private static final String SUSPICIOUS_ACTIVITY_PREFIX = "suspicious:";
    private static final int MAX_LOGIN_ATTEMPTS = 5;
    private static final Duration LOCKOUT_DURATION = Duration.ofMinutes(30);
    
    /**
     * 检查登录安全性
     */
    public SecurityCheckResult checkLoginSecurity(LoginSecurityRequest request) {
        User user = userRepository.findByUsername(request.getUsername())
                .orElse(null);
        
        if (user == null) {
            // 记录无效用户名尝试
            recordSecurityEvent(SecurityEventType.INVALID_USERNAME_ATTEMPT, 
                    null, request.getClientIp(), request.getUserAgent());
            return SecurityCheckResult.failed("用户不存在");
        }
        
        // 检查账户锁定状态
        if (isAccountLocked(user.getId())) {
            return SecurityCheckResult.failed("账户已锁定");
        }
        
        // 检查登录尝试次数
        if (isLoginAttemptsExceeded(user.getId())) {
            lockAccount(user.getId());
            return SecurityCheckResult.failed("登录尝试次数过多,账户已锁定");
        }
        
        // 地理位置检查
        LocationCheckResult locationCheck = checkLocationSecurity(user, request.getClientIp());
        if (locationCheck.isRisky()) {
            recordSecurityEvent(SecurityEventType.SUSPICIOUS_LOCATION, 
                    user.getId(), request.getClientIp(), request.getUserAgent());
        }
        
        // 设备指纹检查
        DeviceCheckResult deviceCheck = checkDeviceSecurity(user, request);
        if (deviceCheck.isNewDevice()) {
            recordSecurityEvent(SecurityEventType.NEW_DEVICE_LOGIN, 
                    user.getId(), request.getClientIp(), request.getUserAgent());
        }
        
        // 时间模式检查
        TimePatternCheckResult timeCheck = checkTimePatternSecurity(user, request.getLoginTime());
        if (timeCheck.isUnusual()) {
            recordSecurityEvent(SecurityEventType.UNUSUAL_TIME_LOGIN, 
                    user.getId(), request.getClientIp(), request.getUserAgent());
        }
        
        // 计算风险评分
        int riskScore = calculateRiskScore(locationCheck, deviceCheck, timeCheck);
        
        SecurityCheckResult result = SecurityCheckResult.builder()
                .success(true)
                .userId(user.getId())
                .riskScore(riskScore)
                .requiresTwoFactor(riskScore > 70 || user.getTwoFactorEnabled())
                .requiresAdditionalVerification(riskScore > 50)
                .locationCheck(locationCheck)
                .deviceCheck(deviceCheck)
                .timeCheck(timeCheck)
                .build();
        
        // 如果风险较高,发送安全警告
        if (riskScore > 80) {
            notificationService.sendSecurityAlert(user, request);
        }
        
        return result;
    }
    
    /**
     * 记录登录尝试
     */
    public void recordLoginAttempt(Long userId, boolean success, String clientIp, String userAgent) {
        String key = LOGIN_ATTEMPT_PREFIX + userId;
        
        if (success) {
            // 登录成功,清除失败记录
            redisTemplate.delete(key);
            recordSecurityEvent(SecurityEventType.LOGIN_SUCCESS, userId, clientIp, userAgent);
        } else {
            // 登录失败,增加失败计数
            redisTemplate.opsForValue().increment(key);
            redisTemplate.expire(key, LOCKOUT_DURATION);
            recordSecurityEvent(SecurityEventType.LOGIN_FAILURE, userId, clientIp, userAgent);
        }
    }
    
    /**
     * 检查是否超过登录尝试次数
     */
    private boolean isLoginAttemptsExceeded(Long userId) {
        String key = LOGIN_ATTEMPT_PREFIX + userId;
        Integer attempts = (Integer) redisTemplate.opsForValue().get(key);
        return attempts != null && attempts >= MAX_LOGIN_ATTEMPTS;
    }
    
    /**
     * 锁定账户
     */
    private void lockAccount(Long userId) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            user.setStatus(UserStatus.LOCKED);
            user.setLockedAt(LocalDateTime.now());
            userRepository.save(user);
            
            // 发送账户锁定通知
            notificationService.sendAccountLockNotification(user);
            
            recordSecurityEvent(SecurityEventType.ACCOUNT_LOCKED, userId, null, null);
            
            log.warn("账户已锁定 - 用户ID: {}", userId);
        }
    }
    
    /**
     * 检查账户是否锁定
     */
    private boolean isAccountLocked(Long userId) {
        User user = userRepository.findById(userId).orElse(null);
        return user != null && user.getStatus() == UserStatus.LOCKED;
    }
    
    /**
     * 地理位置安全检查
     */
    private LocationCheckResult checkLocationSecurity(User user, String clientIp) {
        GeoLocation currentLocation = geoLocationService.getLocation(clientIp);
        List<GeoLocation> userLocations = getUserHistoricalLocations(user.getId());
        
        boolean isNewCountry = userLocations.stream()
                .noneMatch(loc -> loc.getCountryCode().equals(currentLocation.getCountryCode()));
        
        boolean isHighRiskCountry = geoLocationService.isHighRiskCountry(currentLocation.getCountryCode());
        
        double distanceFromUsual = calculateDistanceFromUsualLocations(currentLocation, userLocations);
        
        return LocationCheckResult.builder()
                .currentLocation(currentLocation)
                .isNewCountry(isNewCountry)
                .isHighRiskCountry(isHighRiskCountry)
                .distanceFromUsual(distanceFromUsual)
                .isRisky(isNewCountry || isHighRiskCountry || distanceFromUsual > 1000)
                .build();
    }
    
    /**
     * 设备安全检查
     */
    private DeviceCheckResult checkDeviceSecurity(User user, LoginSecurityRequest request) {
        String deviceFingerprint = deviceFingerprintService.generateFingerprint(
                request.getUserAgent(), request.getScreenResolution(), 
                request.getTimeZone(), request.getLanguage());
        
        List<String> userDevices = getUserDeviceFingerprints(user.getId());
        boolean isNewDevice = !userDevices.contains(deviceFingerprint);
        
        if (isNewDevice) {
            // 保存新设备指纹
            saveUserDeviceFingerprint(user.getId(), deviceFingerprint);
        }
        
        return DeviceCheckResult.builder()
                .deviceFingerprint(deviceFingerprint)
                .isNewDevice(isNewDevice)
                .isTrustedDevice(userDevices.contains(deviceFingerprint))
                .build();
    }
    
    /**
     * 时间模式安全检查
     */
    private TimePatternCheckResult checkTimePatternSecurity(User user, LocalDateTime loginTime) {
        List<LocalDateTime> userLoginTimes = getUserHistoricalLoginTimes(user.getId());
        
        // 分析用户常用登录时间段
        Map<Integer, Long> hourFrequency = userLoginTimes.stream()
                .collect(Collectors.groupingBy(
                        time -> time.getHour(),
                        Collectors.counting()));
        
        int currentHour = loginTime.getHour();
        long currentHourFrequency = hourFrequency.getOrDefault(currentHour, 0L);
        
        // 判断是否为异常时间
        boolean isUnusualTime = currentHourFrequency == 0 && userLoginTimes.size() > 10;
        
        return TimePatternCheckResult.builder()
                .loginTime(loginTime)
                .isUnusual(isUnusualTime)
                .hourFrequency(hourFrequency)
                .build();
    }
    
    /**
     * 计算风险评分
     */
    private int calculateRiskScore(LocationCheckResult locationCheck, 
                                   DeviceCheckResult deviceCheck, 
                                   TimePatternCheckResult timeCheck) {
        int score = 0;
        
        // 地理位置风险
        if (locationCheck.isNewCountry()) score += 30;
        if (locationCheck.isHighRiskCountry()) score += 40;
        if (locationCheck.getDistanceFromUsual() > 1000) score += 20;
        
        // 设备风险
        if (deviceCheck.isNewDevice()) score += 25;
        
        // 时间模式风险
        if (timeCheck.isUnusual()) score += 15;
        
        return Math.min(score, 100);
    }
    
    /**
     * 记录安全事件
     */
    private void recordSecurityEvent(SecurityEventType eventType, Long userId, 
                                     String clientIp, String userAgent) {
        SecurityEvent event = SecurityEvent.builder()
                .eventType(eventType)
                .userId(userId)
                .clientIp(clientIp)
                .userAgent(userAgent)
                .timestamp(LocalDateTime.now())
                .build();
        
        securityEventRepository.save(event);
        
        log.info("安全事件记录 - 类型: {}, 用户ID: {}, IP: {}", 
                eventType, userId, clientIp);
    }
    
    /**
     * 密码安全检查
     */
    public PasswordSecurityResult checkPasswordSecurity(String password, User user) {
        List<String> issues = new ArrayList<>();
        int score = 0;
        
        // 长度检查
        if (password.length() < 8) {
            issues.add("密码长度至少8位");
        } else if (password.length() >= 12) {
            score += 25;
        } else {
            score += 15;
        }
        
        // 复杂度检查
        if (!password.matches(".*[a-z].*")) {
            issues.add("密码必须包含小写字母");
        } else {
            score += 15;
        }
        
        if (!password.matches(".*[A-Z].*")) {
            issues.add("密码必须包含大写字母");
        } else {
            score += 15;
        }
        
        if (!password.matches(".*[0-9].*")) {
            issues.add("密码必须包含数字");
        } else {
            score += 15;
        }
        
        if (!password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':"\\\\|,.<>\\/?].*")) {
            issues.add("密码必须包含特殊字符");
        } else {
            score += 20;
        }
        
        // 常见密码检查
        if (isCommonPassword(password)) {
            issues.add("密码过于常见,请使用更复杂的密码");
            score -= 30;
        }
        
        // 个人信息检查
        if (containsPersonalInfo(password, user)) {
            issues.add("密码不能包含个人信息");
            score -= 20;
        }
        
        score = Math.max(0, Math.min(100, score));
        
        PasswordStrength strength;
        if (score >= 80) {
            strength = PasswordStrength.STRONG;
        } else if (score >= 60) {
            strength = PasswordStrength.MEDIUM;
        } else {
            strength = PasswordStrength.WEAK;
        }
        
        return PasswordSecurityResult.builder()
                .score(score)
                .strength(strength)
                .issues(issues)
                .isAcceptable(issues.isEmpty() && score >= 60)
                .build();
    }
    
    /**
     * 检查是否为常见密码
     */
    private boolean isCommonPassword(String password) {
        // 这里可以维护一个常见密码列表
        Set<String> commonPasswords = Set.of(
                "123456", "password", "123456789", "12345678", "12345",
                "1234567", "1234567890", "qwerty", "abc123", "111111"
        );
        return commonPasswords.contains(password.toLowerCase());
    }
    
    /**
     * 检查密码是否包含个人信息
     */
    private boolean containsPersonalInfo(String password, User user) {
        String lowerPassword = password.toLowerCase();
        
        if (user.getUsername() != null && 
            lowerPassword.contains(user.getUsername().toLowerCase())) {
            return true;
        }
        
        if (user.getEmail() != null) {
            String emailPrefix = user.getEmail().split("@")[0].toLowerCase();
            if (lowerPassword.contains(emailPrefix)) {
                return true;
            }
        }
        
        if (user.getFirstName() != null && 
            lowerPassword.contains(user.getFirstName().toLowerCase())) {
            return true;
        }
        
        if (user.getLastName() != null && 
            lowerPassword.contains(user.getLastName().toLowerCase())) {
            return true;
        }
        
        return false;
    }
    
    // 辅助方法
    private List<GeoLocation> getUserHistoricalLocations(Long userId) {
        // 从数据库获取用户历史登录位置
        return Collections.emptyList();
    }
    
    private double calculateDistanceFromUsualLocations(GeoLocation current, List<GeoLocation> historical) {
        // 计算与常用位置的距离
        return 0.0;
    }
    
    private List<String> getUserDeviceFingerprints(Long userId) {
        // 从数据库获取用户设备指纹
        return Collections.emptyList();
    }
    
    private void saveUserDeviceFingerprint(Long userId, String fingerprint) {
        // 保存用户设备指纹
    }
    
    private List<LocalDateTime> getUserHistoricalLoginTimes(Long userId) {
        // 从数据库获取用户历史登录时间
        return Collections.emptyList();
    }
}

# 技术亮点

# 1. 多维度权限控制

  • 角色层次化管理:支持角色继承和权限聚合
  • 资源级权限:细粒度的资源访问控制
  • 动态权限检查:支持运行时权限验证
  • 权限缓存优化:Redis缓存提升权限检查性能

# 2. 智能安全防护

  • 多因素风险评估:地理位置、设备指纹、时间模式分析
  • 自适应安全策略:根据风险等级调整安全要求
  • 实时威胁检测:异常行为监控和预警
  • 密码安全策略:强密码要求和安全检查

# 3. 全球化用户支持

  • 多租户架构:支持不同地区的用户管理
  • 本地化适配:多语言、多货币、时区支持
  • 合规性保障:GDPR、CCPA等数据保护法规遵循
  • 跨境数据处理:安全的国际数据传输

# 性能优化

# 1. 缓存策略

@Configuration
public class UserCacheConfig {
    
    @Bean
    public CacheManager userCacheManager() {
        RedisCacheManager.Builder builder = RedisCacheManager
                .RedisCacheManagerBuilder
                .fromConnectionFactory(redisConnectionFactory())
                .cacheDefaults(cacheConfiguration());
        
        return builder.build();
    }
    
    private RedisCacheConfiguration cacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(30))
                .serializeKeysWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }
}

# 2. 异步处理

@Configuration
@EnableAsync
public class AsyncConfig {
    
    @Bean(name = "userTaskExecutor")
    public ThreadPoolTaskExecutor userTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setThreadNamePrefix("User-Async-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

# 监控与分析

# 1. 用户行为监控

@Component
public class UserMetrics {
    
    private final MeterRegistry meterRegistry;
    private final Counter userRegistrationCounter;
    private final Counter userLoginCounter;
    private final Timer authenticationTimer;
    
    public UserMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        this.userRegistrationCounter = Counter.builder("user.registration")
                .description("用户注册计数")
                .register(meterRegistry);
        this.userLoginCounter = Counter.builder("user.login")
                .description("用户登录计数")
                .register(meterRegistry);
        this.authenticationTimer = Timer.builder("user.authentication.time")
                .description("用户认证耗时")
                .register(meterRegistry);
    }
    
    public void incrementRegistration() {
        userRegistrationCounter.increment();
    }
    
    public void incrementLogin() {
        userLoginCounter.increment();
    }
    
    public Timer.Sample startAuthenticationTimer() {
        return Timer.start(meterRegistry);
    }
}

# 2. 实时监控面板

@RestController
@RequestMapping("/api/admin/user-dashboard")
public class UserDashboardController {
    
    @Autowired
    private UserAnalyticsService userAnalyticsService;
    
    @GetMapping("/metrics")
    public ResponseEntity<UserMetricsResponse> getUserMetrics() {
        UserMetricsResponse metrics = userAnalyticsService.getUserMetrics();
        return ResponseEntity.ok(metrics);
    }
    
    @GetMapping("/security-events")
    public ResponseEntity<List<SecurityEventSummary>> getSecurityEvents(
            @RequestParam(defaultValue = "24") int hours) {
        List<SecurityEventSummary> events = userAnalyticsService
                .getSecurityEventsSummary(hours);
        return ResponseEntity.ok(events);
    }
    
    @GetMapping("/user-growth")
    public ResponseEntity<UserGrowthData> getUserGrowth(
            @RequestParam(defaultValue = "30") int days) {
        UserGrowthData growth = userAnalyticsService.getUserGrowthData(days);
        return ResponseEntity.ok(growth);
    }
}

# 关键要点

# 技术特色

  • 企业级安全:多层次安全防护和威胁检测
  • 高性能架构:缓存优化和异步处理
  • 全球化支持:多租户和本地化适配
  • 智能分析:用户行为分析和风险评估

# 业务价值

  • 安全可靠:全面的安全防护机制
  • 用户体验:便捷的注册和认证流程
  • 合规保障:满足国际数据保护要求
  • 运营支持:丰富的用户分析和监控功能

# 未来发展

  • AI安全防护:机器学习威胁检测
  • 生物识别:指纹、面部识别等
  • 零信任架构:持续验证和最小权限原则
  • 隐私计算:联邦学习和差分隐私