Spring Boot + MySQL 創建超級管理員

Spring Boot系統創建超管

  • 實現方式
    • 1. 數據庫腳本初始化(最直接的方式)
    • 2. Spring Boot 啟動時自動創建(代碼級初始化)
      • 2.1 實體類定義
      • 2.2 Repository 接口
      • 2.3 初始化組件
      • 2.4 配置密碼加密器
    • 3. 通過接口手動創建(最安全的方式)
      • 3.1 初始化接口
      • 3.2 服務層實現
      • 3.3 數據傳輸對象(DTO)
    • 4. 使用 Flyway/Liquibase 數據庫版本控制
      • 4.1 添加依賴(Maven)
      • 4.2 創建腳本文件
      • 4.3 配置 Flyway(application.properties)
    • 各方法對比與選擇建議
      • 推薦方案
  • 根據項目規模及復雜度選擇方式
    • 1. 小型項目(團隊≤5人,功能簡單)
    • 2. 中型項目(團隊5-20人,業務中等復雜度)
    • 3.大型項目(團隊>20人,復雜業務系統)
    • 總結對比

實現方式

1. 數據庫腳本初始化(最直接的方式)

通過預執行 SQL 腳本創建管理員用戶,適合數據庫初始化階段使用。

實現步驟:

  1. 創建用戶表和角色表
  2. 插入預設角色
  3. 插入加密后的管理員用戶
-- 1. 創建用戶表
CREATE TABLE `sys_user` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '用戶ID',`username` varchar(50) NOT NULL COMMENT '用戶名',`password` varchar(100) NOT NULL COMMENT '加密密碼',`email` varchar(100) DEFAULT NULL COMMENT '郵箱',`status` tinyint NOT NULL DEFAULT '1' COMMENT '狀態(0:禁用,1:正常)',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',PRIMARY KEY (`id`),UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系統用戶';-- 2. 創建角色表
CREATE TABLE `sys_role` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',`role_name` varchar(50) NOT NULL COMMENT '角色名稱',`role_key` varchar(50) NOT NULL COMMENT '角色標識',PRIMARY KEY (`id`),UNIQUE KEY `uk_role_key` (`role_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';-- 3. 創建用戶角色關聯表
CREATE TABLE `sys_user_role` (`user_id` bigint NOT NULL COMMENT '用戶ID',`role_id` bigint NOT NULL COMMENT '角色ID',PRIMARY KEY (`user_id`,`role_id`),KEY `fk_role_id` (`role_id`),CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`),CONSTRAINT `fk_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶角色關聯表';-- 4. 插入預設角色(超級管理員角色)
INSERT INTO `sys_role` (`role_name`, `role_key`) VALUES ('超級管理員', 'ROLE_SUPER_ADMIN');-- 5. 插入管理員用戶(密碼使用BCrypt加密,原始密碼:Admin@123456)
INSERT INTO `sys_user` (`username`, `password`, `email`) 
VALUES ('admin', '$2a$10$G9h.C4O4X2r0U8F5L2j/9O3lQ5VQZJZJZJZJZJZJZJZJZJZJZJZ',  -- BCrypt加密后的密碼'admin@example.com'
);-- 6. 關聯用戶與角色
INSERT INTO `sys_user_role` (`user_id`, `role_id`) 
VALUES ((SELECT id FROM sys_user WHERE username = 'admin'),(SELECT id FROM sys_role WHERE role_key = 'ROLE_SUPER_ADMIN')
);

注意事項:

  • 密碼必須使用加密算法(如 BCrypt),不可明文存儲
  • 可通過 在線 BCrypt 加密工具 生成加密后的密碼
  • 腳本執行時機:數據庫初始化時(如項目首次部署)

2. Spring Boot 啟動時自動創建(代碼級初始化)

利用 Spring 的 CommandLineRunner 接口,在應用啟動時自動檢查并創建管理員用戶。

CommandLineRunner接口用于定義應用程序啟動后需要立即執行的邏輯。(編寫一個類實現該接口,此時需要重寫該接口中的run()方法,將需要實現的代碼編寫至該run()方法中,該方法會在 Spring Boot 應用完全啟動后執行)

實現步驟:

  1. 定義用戶和角色實體類
  2. 創建數據訪問層(Repository)
  3. 實現初始化邏輯

2.1 實體類定義

// User.java
@Entity
@Table(name = "sys_user")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(unique = true, nullable = false)private String username;@Column(nullable = false)private String password;private String email;private Integer status = 1; // 1-正常,0-禁用@Column(name = "create_time")private LocalDateTime createTime = LocalDateTime.now();@ManyToMany(fetch = FetchType.EAGER)@JoinTable(name = "sys_user_role",joinColumns = @JoinColumn(name = "user_id"),inverseJoinColumns = @JoinColumn(name = "role_id"))private Set<Role> roles = new HashSet<>();// 省略 getter/setter
}// Role.java
@Entity
@Table(name = "sys_role")
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "role_name")private String roleName;@Column(name = "role_key", unique = true)private String roleKey;// 省略 getter/setter
}

2.2 Repository 接口

// UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {Optional<User> findByUsername(String username);
}// RoleRepository.java
public interface RoleRepository extends JpaRepository<Role, Long> {Optional<Role> findByRoleKey(String roleKey);
}

2.3 初始化組件

@Component
public class AdminUserInitializer implements CommandLineRunner {@Autowiredprivate UserRepository userRepository;@Autowiredprivate RoleRepository roleRepository;@Autowiredprivate PasswordEncoder passwordEncoder; 		// Spring Security 提供的密碼加密器// CommandLineRunner 的 run() 方法會在 Spring Boot 應用完全啟動后執行,具體時機:① 所有 Spring 容器中的 Bean 都已初始化完成(依賴注入完成),② 嵌入式服務器(如 Tomcat)已啟動但還未開始接收請求,③ 執行順序在 @PostConstruct 注解之后(@PostConstruct 是 Bean 初始化時執行,早于 CommandLineRunner)。簡單說:應用啟動成功后,第一個用戶請求到達前,run() 方法會被自動調用。// 確保應用啟動時,數據庫中存在一個可用的超級管理員賬戶(如果不存在則自動創建)。@Overridepublic void run(String... args) throws Exception {createAdminRoleIfNotExists();createAdminUserIfNotExists();}// 創建超級管理員角色(如果不存在)private void createAdminRoleIfNotExists() {if (roleRepository.findByRoleKey("ROLE_SUPER_ADMIN").isEmpty()) {Role adminRole = new Role();adminRole.setRoleName("超級管理員");adminRole.setRoleKey("ROLE_SUPER_ADMIN");roleRepository.save(adminRole);}}// 創建管理員用戶(如果不存在)private void createAdminUserIfNotExists() {if (userRepository.findByUsername("admin").isEmpty()) {// 獲取管理員角色Role adminRole = roleRepository.findByRoleKey("ROLE_SUPER_ADMIN").orElseThrow(() -> new RuntimeException("超級管理員角色不存在"));// 創建用戶User adminUser = new User();adminUser.setUsername("admin");adminUser.setPassword(passwordEncoder.encode("Admin@123456")); // 加密密碼adminUser.setEmail("admin@example.com");adminUser.getRoles().add(adminRole);userRepository.save(adminUser);System.out.println("超級管理員用戶創建成功:admin/Admin@123456");}}
}

2.4 配置密碼加密器

@Configuration
public class SecurityConfig {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(); // 使用BCrypt加密算法}
}

優點:

  • 自動化程度高,無需手動執行腳本
  • 可通過代碼邏輯靈活控制創建條件

3. 通過接口手動創建(最安全的方式)

系統部署后,通過一個臨時的初始化接口創建管理員用戶,適合生產環境。

實現步驟:

  1. 創建一個初始化接口
  2. 添加安全限制(如僅允許本地訪問)
  3. 通過接口調用創建管理員

3.1 初始化接口

@RestController
@RequestMapping("/init")
public class InitController {@Autowiredprivate UserService userService;// 僅允許本地訪問(生產環境安全限制)@PostMapping("/admin")public Result createAdmin(@RequestBody AdminInitDTO dto) {// 檢查請求來源是否為本地if (!isLocalRequest()) {return Result.fail("僅允許本地訪問");}// 檢查管理員是否已存在if (userService.existsByUsername("admin")) {return Result.fail("管理員已存在");}// 創建管理員userService.createAdmin(dto);return Result.success("管理員創建成功");}// 判斷請求是否來自本地private boolean isLocalRequest() {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();String ip = request.getRemoteAddr();return "127.0.0.1".equals(ip) || "localhost".equals(ip);}
}

3.2 服務層實現

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate RoleRepository roleRepository;@Autowiredprivate PasswordEncoder passwordEncoder;@Transactionalpublic void createAdmin(AdminInitDTO dto) {// 創建角色Role adminRole = new Role();adminRole.setRoleName("超級管理員");adminRole.setRoleKey("ROLE_SUPER_ADMIN");roleRepository.save(adminRole);// 創建用戶User adminUser = new User();adminUser.setUsername("admin");adminUser.setPassword(passwordEncoder.encode(dto.getPassword()));adminUser.setEmail(dto.getEmail());adminUser.getRoles().add(adminRole);userRepository.save(adminUser);}public boolean existsByUsername(String username) {return userRepository.findByUsername(username).isPresent();}
}

3.3 數據傳輸對象(DTO)

public class AdminInitDTO {private String password; // 管理員密碼(前端傳入明文,后端加密)private String email;    // 管理員郵箱// 省略 getter/setter
}

優點:

  • 安全性高,避免硬編碼密碼
  • 可在系統部署后手動觸發,靈活控制時機
  • 適合生產環境使用

4. 使用 Flyway/Liquibase 數據庫版本控制

通過數據庫版本控制工具管理初始化腳本,適合團隊協作和版本化部署。

實現步驟:

  1. 添加 Flyway 依賴
  2. 創建初始化腳本
  3. 配置 Flyway

4.1 添加依賴(Maven)

<dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId>
</dependency>

4.2 創建腳本文件

src/main/resources/db/migration 目錄下創建 V1__init_admin_user.sql

-- 內容同方法一中的SQL腳本
CREATE TABLE `sys_user` (...);
CREATE TABLE `sys_role` (...);
CREATE TABLE `sys_user_role` (...);
INSERT INTO `sys_role` (...) VALUES (...);
INSERT INTO `sys_user` (...) VALUES (...);
INSERT INTO `sys_user_role` (...) VALUES (...);

4.3 配置 Flyway(application.properties)

# Flyway配置
spring.flyway.enabled=true
spring.flyway.baseline-on-migrate=true
spring.flyway.clean-disabled=true # 禁用清理功能(生產環境安全)

優點:

  • 腳本版本化管理,適合團隊協作
  • 自動執行,無需手動干預
  • 支持數據庫變更的追溯和回滾

各方法對比與選擇建議

方法適用場景安全性自動化程度
數據庫腳本初始化簡單項目、快速部署
啟動時自動創建開發/測試環境、小型項目
接口手動創建生產環境、對安全性要求高
Flyway/Liquibase團隊協作、大型項目、版本化部署

推薦方案

  • 開發環境:使用 啟動時自動創建Flyway
  • 生產環境:優先使用 接口手動創建Flyway(配合加密配置)

無論選擇哪種方法,都需遵循以下安全原則:

  1. 密碼必須加密存儲(推薦 BCrypt 或 Argon2)
  2. 首次登錄后強制修改默認密碼
  3. 最小權限原則(超級管理員僅用于系統初始化)
  4. 敏感配置(如初始密碼)避免硬編碼,通過環境變量或配置中心注入

根據項目規模及復雜度選擇方式

在 Spring Boot + MySQL 系統中創建第一個超級管理員用戶的方案選擇,應根據項目規模和復雜度進行調整。以下是針對大、中、小型項目在生產環境中的最佳實踐:

1. 小型項目(團隊≤5人,功能簡單)

推薦方案:應用啟動時自動創建(帶安全開關)

適合場景:快速部署、維護成本低的小型應用,如內部管理工具、簡單的業務系統。

實現步驟:

  1. 數據庫表結構(同上一回答,包含用戶、角色和關聯表)

  2. 安全配置類

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(12); // 工作因子12,安全性較高}
    }
    
  3. 帶開關的初始化器

    @Component
    public class AdminUserInitializer implements CommandLineRunner {@Value("${app.initialize-admin:false}") // 默認關閉,生產環境需顯式開啟private boolean initializeAdmin;@Value("${app.admin.username:admin}")private String adminUsername;@Value("${app.admin.email:admin@example.com}")private String adminEmail;@Value("${app.admin.initial-password}") // 必須在環境變量中設置private String initialPassword;private final UserRepository userRepository;private final RoleRepository roleRepository;private final PasswordEncoder passwordEncoder;@Autowiredpublic AdminUserInitializer(UserRepository userRepository, RoleRepository roleRepository,PasswordEncoder passwordEncoder) {this.userRepository = userRepository;this.roleRepository = roleRepository;this.passwordEncoder = passwordEncoder;}@Overridepublic void run(String... args) {if (initializeAdmin) {createAdminUserIfNotExists();}}private void createAdminUserIfNotExists() {if (userRepository.findByUsername(adminUsername).isEmpty()) {// 驗證初始密碼強度if (!isPasswordStrong(initialPassword)) {throw new IllegalArgumentException("Initial password does not meet security requirements");}Role adminRole = roleRepository.findByName("ROLE_ADMIN").orElseGet(() -> {Role role = new Role();role.setName("ROLE_ADMIN");return roleRepository.save(role);});User adminUser = new User();adminUser.setUsername(adminUsername);adminUser.setPassword(passwordEncoder.encode(initialPassword));adminUser.setEmail(adminEmail);adminUser.setEnabled(true);adminUser.setForcePasswordChange(true); // 強制首次登錄修改密碼adminUser.getRoles().add(adminRole);userRepository.save(adminUser);log.info("Admin user created successfully. Username: {}", adminUsername);}}// 密碼強度檢查private boolean isPasswordStrong(String password) {return password.length() >= 12 && password.matches(".*[A-Z].*")&& password.matches(".*[a-z].*")&& password.matches(".*\\d.*")&& password.matches(".*[!@#$%^&*()].*");}
    }
    
  4. 配置文件

    # application-prod.properties
    app.initialize-admin=false  # 默認關閉
    app.admin.username=admin
    app.admin.email=admin@example.com
    # 生產環境通過環境變量設置: export APP_ADMIN_INITIAL_PASSWORD=強密碼
    
  5. 首次啟動命令

    # 僅首次啟動時使用,創建完成后禁用
    APP_ADMIN_INITIAL_PASSWORD='StrongP@ssw0rd2024' java -jar app.jar --spring.profiles.active=prod --app.initialize-admin=true
    

優點:實現簡單,部署便捷,適合資源有限的小團隊

缺點:安全性中等,需要手動確保初始化后關閉開關

2. 中型項目(團隊5-20人,業務中等復雜度)

推薦方案:命令行工具初始化 + 密碼重置機制

適合場景:有專職運維人員,需要更規范的部署流程的應用,如企業級SaaS、業務管理系統。

實現步驟:

  1. 創建專用的命令行工具

    @ShellComponent
    public class AdminUserCommand {private final AdminUserService adminUserService;private final Logger log = LoggerFactory.getLogger(AdminUserCommand.class);@Autowiredpublic AdminUserCommand(AdminUserService adminUserService) {this.adminUserService = adminUserService;}@ShellMethod(key = "create-admin", value = "Creates the initial admin user")public String createAdmin(@ShellOption(help = "Admin username") String username,@ShellOption(help = "Admin email") String email,@ShellOption(help = "Temporary password") String tempPassword) {try {// 檢查用戶是否已存在if (adminUserService.existsByUsername(username)) {return "Error: Admin user with username '" + username + "' already exists";}// 創建管理員用戶String result = adminUserService.createInitialAdmin(username, email, tempPassword);log.info("Admin user '{}' created successfully", username);return result + "\nPlease ensure to change this password immediately after first login";} catch (Exception e) {log.error("Failed to create admin user", e);return "Failed to create admin user: " + e.getMessage();}}@ShellMethod(key = "generate-admin-token", value = "Generates a one-time token for admin password reset")public String generateAdminToken(@ShellOption(help = "Admin username") String username) {try {String token = adminUserService.generatePasswordResetToken(username);return "One-time reset token (valid for 10 minutes): " + token;} catch (Exception e) {return "Error generating token: " + e.getMessage();}}
    }
    
  2. 服務層實現

    @Service
    @Transactional
    public class AdminUserService {private final UserRepository userRepository;private final RoleRepository roleRepository;private final PasswordEncoder passwordEncoder;private final PasswordResetTokenRepository tokenRepository;// 構造函數注入依賴...public String createInitialAdmin(String username, String email, String tempPassword) {// 密碼強度驗證...Role adminRole = getOrCreateAdminRole();User admin = new User();admin.setUsername(username);admin.setEmail(email);admin.setPassword(passwordEncoder.encode(tempPassword));admin.setEnabled(true);admin.setForcePasswordChange(true);admin.setLastPasswordChangeDate(LocalDateTime.now());admin.getRoles().add(adminRole);userRepository.save(admin);return "Admin user created with username: " + username;}public String generatePasswordResetToken(String username) {User user = userRepository.findByUsername(username).orElseThrow(() -> new IllegalArgumentException("User not found"));// 生成唯一令牌,有效期10分鐘String token = UUID.randomUUID().toString();PasswordResetToken resetToken = new PasswordResetToken();resetToken.setToken(token);resetToken.setUser(user);resetToken.setExpiryDate(LocalDateTime.now().plusMinutes(10));tokenRepository.save(resetToken);return token;}// 其他方法...
    }
    
  3. 使用流程

    # 1. 啟動應用的命令行模式
    java -jar app.jar --spring.shell.interactive.enabled=true# 2. 在shell中執行創建命令
    shell:> create-admin --username superadmin --email admin@company.com --tempPassword 'TempP@ss123!'# 3. 生成密碼重置令牌
    shell:> generate-admin-token --username superadmin# 4. 通過前端頁面或API使用令牌重置密碼
    

優點:安全性高,操作可審計,符合規范流程

缺點:需要額外開發命令行工具,增加少量開發成本

3.大型項目(團隊>20人,復雜業務系統)

推薦方案:初始化腳本 + 密鑰管理 + 多因素認證

適合場景:企業核心系統、金融科技、高安全性要求的應用,有完善的DevOps流程。

實現步驟:

  1. 數據庫設計與遷移策略:使用FlywayLiquibase進行版本化數據庫遷移,確保表結構創建和初始數據插入可追溯。

    # 數據表創建`V1_schema_init.sql`
    -- 用戶表
    CREATE TABLE users (id BIGINT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,password_hash VARCHAR(255) NOT NULL,email VARCHAR(100) NOT NULL UNIQUE,enabled BOOLEAN NOT NULL DEFAULT FALSE,force_password_change BOOLEAN NOT NULL DEFAULT TRUE,last_password_change TIMESTAMP,mfa_enabled BOOLEAN NOT NULL DEFAULT FALSE,created_by VARCHAR(50) NOT NULL,created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,updated_by VARCHAR(50),updated_at TIMESTAMP,CONSTRAINT valid_email CHECK (email REGEXP '^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$')
    );-- 角色表
    CREATE TABLE roles (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(50) NOT NULL UNIQUE,description VARCHAR(255),created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
    );-- 權限表
    CREATE TABLE permissions (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL UNIQUE,description VARCHAR(255),created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
    );-- 用戶角色關聯表
    CREATE TABLE user_roles (user_id BIGINT NOT NULL,role_id BIGINT NOT NULL,assigned_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,assigned_by VARCHAR(50) NOT NULL,PRIMARY KEY (user_id, role_id),FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,FOREIGN KEY (role_id) REFERENCES roles(id)
    );-- 角色權限關聯表
    CREATE TABLE role_permissions (role_id BIGINT NOT NULL,permission_id BIGINT NOT NULL,PRIMARY KEY (role_id, permission_id),FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE,FOREIGN KEY (permission_id) REFERENCES permissions(id)
    );-- 操作審計日志表
    CREATE TABLE audit_logs (id BIGINT AUTO_INCREMENT PRIMARY KEY,user_id BIGINT,operation VARCHAR(100) NOT NULL,entity_type VARCHAR(50) NOT NULL,entity_id VARCHAR(50),details JSON,ip_address VARCHAR(45),user_agent TEXT,created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,FOREIGN KEY (user_id) REFERENCES users(id)
    );
    
    # 數據庫初始化腳本`V2_initial_roles.sql`
    -- 創建基礎角色
    INSERT INTO roles (name, description) VALUES ('ROLE_SUPER_ADMIN', '系統最高權限管理員'),('ROLE_ADMIN', '普通管理員'),('ROLE_SECURITY_AUDITOR', '安全審計員');-- 插入核心權限
    INSERT INTO permissions (name, description) VALUES('USER_CREATE', '創建用戶'),('USER_DELETE', '刪除用戶'),('USER_UPDATE', '更新用戶'),('USER_VIEW', '查看用戶'),('ROLE_MANAGE', '管理角色'),('PERMISSION_MANAGE', '管理權限'),('SYSTEM_CONFIG', '系統配置'),('AUDIT_VIEW', '查看審計日志');	-- 為超級管理員角色分配所有權限
    INSERT INTO role_permissions (role_id, permission_id)
    SELECT (SELECT id FROM roles WHERE name = 'ROLE_SUPER_ADMIN'),id 
    FROM permissions;
    
  2. 密碼生成與管理工具:開發專用工具生成符合 NIST 標準的強密碼,并使用 BCrypt 算法 (工作因子 12+) 進行哈希處理。

    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import java.security.SecureRandom;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;public class AdminPasswordUtil {private static final int PASSWORD_LENGTH = 20;private static final BCryptPasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder(14);private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";private static final String LOWER = "abcdefghijklmnopqrstuvwxyz";private static final String DIGITS = "0123456789";private static final String SYMBOLS = "!@#$%^&*()_-+=[{]};:<>|./?";private static final SecureRandom RANDOM = new SecureRandom();public static void main(String[] args) {// 生成符合NIST標準的強密碼String rawPassword = generateSecurePassword();String encodedPassword = PASSWORD_ENCODER.encode(rawPassword);System.out.println("=== 生成的超級管理員初始密碼 ===");System.out.println("明文密碼: " + rawPassword);System.out.println("BCrypt哈希: " + encodedPassword);System.out.println("==============================");System.out.println("警告: 此密碼僅顯示一次,使用后立即銷毀記錄");}private static String generateSecurePassword() {// 確保密碼包含所有類型的字符List<Character> passwordChars = new ArrayList<>(PASSWORD_LENGTH);// 至少包含每種類型的字符passwordChars.add(UPPER.charAt(RANDOM.nextInt(UPPER.length())));passwordChars.add(LOWER.charAt(RANDOM.nextInt(LOWER.length())));passwordChars.add(DIGITS.charAt(RANDOM.nextInt(DIGITS.length())));passwordChars.add(SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())));// 填充剩余字符String allChars = UPPER + LOWER + DIGITS + SYMBOLS;for (int i = 4; i < PASSWORD_LENGTH; i++) {passwordChars.add(allChars.charAt(RANDOM.nextInt(allChars.length())));}// 隨機打亂順序Collections.shuffle(passwordChars, RANDOM);// 轉換為字符串StringBuilder password = new StringBuilder(PASSWORD_LENGTH);for (Character c : passwordChars) {password.append(c);}return password.toString();}
    }
    
  3. 創建超級管理員腳本:使用單獨的數據庫遷移腳本創建超級管理員,密碼哈希通過前面的工具生成。

    # 創建超管的數據庫腳本`V3_create_super_admin.sql`
    -- 注意: 此腳本中的密碼哈希必須通過AdminPasswordUtil生成
    -- 生產環境部署前必須替換為新生成的哈希值
    INSERT INTO users (username, password_hash, email, enabled, force_password_change,created_by
    ) VALUES ('superadmin',-- 這里替換為通過AdminPasswordUtil生成的BCrypt哈希'$2a$14$示例哈希值需替換','security-admin@yourcompany.com',TRUE,TRUE,'SYSTEM_INIT'
    );-- 為超級管理員分配角色
    INSERT INTO user_roles (user_id, role_id, assigned_by)
    VALUES ((SELECT id FROM users WHERE username = 'superadmin'),(SELECT id FROM roles WHERE name = 'ROLE_SUPER_ADMIN'),'SYSTEM_INIT'
    );-- 記錄審計日志
    INSERT INTO audit_logs (operation, entity_type, entity_id, details, created_at
    ) VALUES ('INITIAL_ADMIN_CREATED','USER',(SELECT id FROM users WHERE username = 'superadmin'),JSON_OBJECT('action', 'Initial super admin creation','username', 'superadmin','creation_method', 'database_migration','security_note', 'Force password change required'),CURRENT_TIMESTAMP
    );
    
  4. 部署流程與安全控制:整合 CI/CD 流程,確保所有操作可審計并符合安全規范。

    # deploy-init.yaml
    name: Deploy Initial Setupon:workflow_dispatch:inputs:environment:description: 'Deployment environment'required: truedefault: 'production'type: choiceoptions:- production- stagingapprover:description: 'Approver username'required: trueticketNumber:description: 'Change management ticket number'required: truejobs:security-scan:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Run SQL lintingrun: |# 檢查SQL腳本安全性sqlfluff lint src/main/resources/db/migration/generate-credentials:needs: security-scanruns-on: ubuntu-latestoutputs:password_hash: ${{ steps.generate.outputs.hash }}steps:- uses: actions/checkout@v4- name: Generate admin credentialsid: generaterun: |# 編譯密碼生成工具javac -d target src/main/java/com/company/util/AdminPasswordUtil.java# 生成密碼并捕獲輸出output=$(java -cp target com.company.util.AdminPasswordUtil)raw_password=$(echo "$output" | grep "明文密碼" | cut -d: -f2 | xargs)password_hash=$(echo "$output" | grep "BCrypt哈希" | cut -d: -f2 | xargs)# 輸出哈希供后續步驟使用echo "hash=$password_hash" >> $GITHUB_OUTPUT# 將明文密碼存儲到安全的密鑰管理系統aws secretsmanager create-secret \--name "${{ github.ref_name }}/admin/initial-password" \--secret-string "$raw_password" \--description "Initial superadmin password created by ${{ github.actor }} for ticket ${{ github.event.inputs.ticketNumber }}"# 記錄審計信息echo "Initial password generated for ${{ github.event.inputs.environment }} by ${{ github.actor }}" >> audit.logupdate-migration-script:needs: generate-credentialsruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Replace password hash in migration scriptrun: |# 使用生成的哈希值替換腳本中的占位符sed -i "s|'\\$2a\\$14\\$示例哈希值需替換'|'${{ needs.generate-credentials.outputs.password_hash }}'|g" \src/main/resources/db/migration/V3__create_super_admin.sql- name: Commit updated scriptrun: |git config --global user.name "CI Bot"git config --global user.email "ci@company.com"git add src/main/resources/db/migration/V3__create_super_admin.sqlgit commit -m "Update admin password hash for ${{ github.event.inputs.environment }} [ticket: ${{ github.event.inputs.ticketNumber }}]"git pushrun-migrations:needs: update-migration-scriptruns-on: ubuntu-latestenvironment: ${{ github.event.inputs.environment }}steps:- uses: actions/checkout@v4- name: Run database migrationsrun: |# 執行Flyway遷移java -jar flyway/flyway-commandline-10.10.0.jar migrate \-url=jdbc:mysql://${{ secrets.DB_HOST }}:${{ secrets.DB_PORT }}/${{ secrets.DB_NAME }} \-user=${{ secrets.DB_USER }} \-password=${{ secrets.DB_PASSWORD }} \-locations=filesystem:src/main/resources/db/migration- name: Log deploymentrun: |# 記錄部署信息到審計系統curl -X POST ${{ secrets.AUDIT_SERVICE_URL }} \-H "Authorization: Bearer ${{ secrets.AUDIT_SERVICE_TOKEN }}" \-H "Content-Type: application/json" \-d '{"event": "SUPER_ADMIN_CREATED","environment": "${{ github.event.inputs.environment }}","user": "${{ github.actor }}","approver": "${{ github.event.inputs.approver }}","ticket": "${{ github.event.inputs.ticketNumber }}","timestamp": "'"$(date -u +"%Y-%m-%dT%H:%M:%SZ")"'"}'
    
  5. 首次登錄強制安全措施:實現首次登錄必須修改密碼并配置多因素認證 (MFA)。

    import jakarta.servlet.FilterChain;
    import jakarta.servlet.ServletException;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.web.filter.OncePerRequestFilter;
    import java.io.IOException;public class ForceChangePasswordFilter extends OncePerRequestFilter {private final UserService userService;// 構造函數注入UserService@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {Authentication auth = SecurityContextHolder.getContext().getAuthentication();if (auth != null && auth.isAuthenticated() && !request.getRequestURI().contains("/api/auth/change-password")) {String username = auth.getName();boolean forceChange = userService.needsPasswordChange(username);if (forceChange) {response.setStatus(HttpServletResponse.SC_FORBIDDEN);response.setContentType("application/json");response.getWriter().write("{\"error\": \"FORCE_PASSWORD_CHANGE_REQUIRED\", \"message\": \"You must change your password before proceeding\"}");return;}}filterChain.doFilter(request, response);}
    }
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.web.SecurityFilterChain;
    import org.springframework.security.web.authentication.forcechangepassword.ForceChangePasswordFilter;@Configuration
    @EnableWebSecurity
    public class SecurityConfig {private final ForceChangePasswordFilter forceChangePasswordFilter;private final MfaVerificationFilter mfaVerificationFilter;// 構造函數注入依賴@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(auth -> auth.requestMatchers("/api/auth/login", "/api/auth/change-password", "/api/auth/setup-mfa").permitAll().requestMatchers("/api/admin/**").hasRole("SUPER_ADMIN").anyRequest().authenticated()).addFilterAfter(forceChangePasswordFilter, UsernamePasswordAuthenticationFilter.class).addFilterAfter(mfaVerificationFilter, ForceChangePasswordFilter.class).sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(true)).csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())).headers(headers -> headers.contentSecurityPolicy("default-src 'self'; script-src 'self'").and().frameOptions().deny());return http.build();}
    }
    

優點:安全性極高,符合審計要求,適合高安全級別的系統

缺點:實施復雜,需要完整的DevOps和密鑰管理體系

總結對比

項目規模推薦方案核心特點安全級別實施復雜度
小型項目啟動時自動創建(帶開關)簡單快捷,適合快速部署
中型項目命令行工具初始化可審計,流程規范
大型項目初始化腳本 + 密鑰管理符合安全標準,可追溯極高

所有方案的共同原則:

  1. 絕不硬編碼密碼到代碼中
  2. 強制首次登錄修改密碼
  3. 使用強哈希算法存儲密碼
  4. 記錄初始化操作日志
  5. 超級管理員權限最小化

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98908.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98908.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98908.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

楊輝三角**

一、題目給定一個非負整數 numRows&#xff0c;生成「楊輝三角」的前 numRows 行。在「楊輝三角」中&#xff0c;每個數是它左上方和右上方的數的和。示例 1:輸入: numRows 5 輸出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2:輸入: numRows 1 輸出: [[1]]提示:1 <…

Vue3 的單文件組件(.vue 文件)中,在 <script>、<template>、<style> 標簽外輸入內容不會導致程序報錯

在 <script>、<template>、<style> 標簽外首行誤輸入內容 vtsvts <script setup lang"ts" name"BaseDocxPreviewDialog"> /*** docx文件預覽模態框組件*/ defineOptions({ name: "BaseDocxPreviewDialog" }); import { …

LVS負載均衡群集和LVS+Keepalived群集

1、群集 1.1群集的含義 由多臺主機構成&#xff0c;但對外只表現為一個整體&#xff0c;只提供一個訪問入口&#xff08;域名與IP地址&#xff09;&#xff0c;相當于一臺大型計算機。 1.2 企業群集分類 負載均衡群集&#xff1a;提高應用系統的響應能力、盡可能處理更多的…

LeetCode力扣-hot100系列(5)

這一篇主要講一講回溯&#xff0c;除了N皇后問題是困難題&#xff0c;不過N皇后知道了咋做也不難。回溯整體上還是好做的&#xff0c;直到套路容易做出來&#xff0c;題目容易理解。回溯[1]全排列問&#xff1a;給定一個不含重復數字的數組 nums &#xff0c;返回其 所有可能的…

機器學習05——多分類學習與類別不平衡(一對一、一對其余、多對多)

上一章&#xff1a;機器學習04——決策樹 下一章&#xff1a;機器學習06——支持向量機 機器學習實戰項目&#xff1a;【從 0 到 1 落地】機器學習實操項目目錄&#xff1a;覆蓋入門到進階&#xff0c;大學生就業 / 競賽必備 文章目錄一、多分類學習&#xff08;一&#xff09;…

2025.9.11總結

閱讀《拿鐵因素》有感昨天看完《拿鐵因素》&#xff0c;這本書讓我明白&#xff0c;如果不去主動去管理自己的財務&#xff0c;解決自己從前的財務問題&#xff0c;我很難過上自己想要的生活。今天就所讀的內容&#xff0c;探究如何將這本書的內容運用到自己的一個日常生活中。…

Android,Jetpack Compose,坦克大戰游戲案例Demo

代碼如下&#xff08;這只是個簡單案例而已&#xff09;&#xff1a; package com.example.myapplicationimport android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.Canvas impo…

zookeeper是啥

ZooKeeper是一個開源的分布式協調服務&#xff0c;主要用于解決分布式系統中的數據一致性、狀態同步和協作問題?。它通過提供高可用、強一致性的服務&#xff0c;成為分布式系統的“指揮中心”?。以下是其核心功能和應用場景&#xff1a;核心功能 分布式同步? 通過原子廣播協…

【開題答辯全過程】以 基于Android的智慧旅游APP開發為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

如何選擇?SEO 與 GEO 的 5 個核心分野

在 30 秒內&#xff0c;以下是您需要了解的有關 SEO 和 GEO 之間差異的信息&#xff1a; SEO&#xff08;搜索引擎優化&#xff09;&#xff1a;讓您的網站出現在 Google 搜索中。目標&#xff1a;吸引用戶點擊您的鏈接。GEO&#xff08;生成引擎優化&#xff09;&#xff1a;…

基于MATLAB的光學CCD全息成像仿真程序實現

基于MATLAB的光學CCD全息成像仿真程序實現一、流程 #mermaid-svg-g3dkhZSC3Go4a2kH {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-g3dkhZSC3Go4a2kH .error-icon{fill:#552222;}#mermaid-svg-g3dkhZSC3Go4a2kH .er…

Java大廠面試實錄:產業互聯網大數據與AI服務場景下的微服務與智能搜索(含詳細解讀)

Java大廠面試實錄&#xff1a;產業互聯網大數據與AI服務場景下的微服務與智能搜索&#xff08;含詳細解讀&#xff09; 場景開場 &#x1f3ed;&#x1f984; 午后陽光正好&#xff0c;王老登背著“Java一把梭”的背包&#xff0c;精神抖擻地走進了產業互聯網大數據與AI服務大廠…

Win_Server遠程桌面(RDP)服務調用GPU并提上傳輸幀率和USB設備重定向

說明&#xff1a;Windows遠程桌面服務&#xff08; RDP &#xff09;&#xff0c;RDP服務是可以無顯卡運行的&#xff0c;顯示遠程桌面的時候并不調用顯卡&#xff0c;可以做一些基本的管理操作&#xff0c;為提升RDP的性能&#xff0c;可以開啟顯卡加速&#xff08; OpenGL&am…

Docker(⑤Kali Linux-HexStrike AI安裝)

卸載 WSL 里的 Ubuntuwsl --unregister Ubuntu查看當前已安裝的發行版wsl --list --verbose下載kali-linuxwsl --install -d kali-linuxKali 服務端安裝sudo apt update && sudo apt upgrade -y sudo apt install python3 python3-venv python3-pip git -y克隆源碼 &am…

查找算法和遞推算法

查找算法題目 1&#xff1a;找班級里的 “小明星”題目描述&#xff1a;班級有 10 個同學的編號&#xff08;1 - 10&#xff09;&#xff0c;輸入一個編號&#xff0c;判斷是否是 “小明星”&#xff08;假設編號為 5 的是小明星&#xff09;&#xff0c;是就輸出 “找到小明星…

2025 年PT展前瞻:人工智能+如何走進普通人的生活?

導讀&#xff1a;2025年&#xff0c;人工智能正在加速融入日常生活&#xff0c;提升著每一個普通人的幸福感與獲得感。清晨&#xff0c;智能手環在你最淺的睡眠階段輕柔震動&#xff0c;用最科學的方式將你喚醒&#xff1b;通勤路上&#xff0c;智能網聯汽車早已規劃好躲避擁堵…

1-機器學習與大模型開發數學教程-第0章 預備知識-0-1 集合與邏輯基礎(集合運算、命題邏輯、量詞)

在正式進入機器學習與大模型的數學核心之前&#xff0c;我們需要先打好“語言”和“邏輯”的基礎。 這一章會從 集合與邏輯 入手&#xff0c;它們就像是編程中的語法規則&#xff1a; 集合告訴我們“對象屬于不屬于某個范圍”&#xff1b;邏輯告訴我們“命題對不對、能不能推出…

字節 Trae vs 騰訊 CodeBuddy vs 阿里 Qoder:三大 AI-IDE 集成 OneCode 深度對比與體驗測評

一、對比背景&#xff1a;AI-IDE 與低代碼融合的行業必然性 在低代碼開發進入 “AI 賦能期” 的 2025 年&#xff0c;AI 驅動的集成開發環境&#xff08;AI-IDE&#xff09;已成為低代碼平臺效率提升的核心載體。全球 AI-IDE 市場規模突破 50 億美元&#xff0c;年增長率超 70…

DeerFlow 與 MCP 區別深度解析

目錄 引言 一、DeerFlow 與 MCP 的詳細概念說明 1. DeerFlow&#xff1a;面向研究自動化的多智能體應用框架 2. MCP&#xff1a;連接 AI 模型與外部系統的標準化通信協議 二、核心定位&#xff1a;應用框架與通信協議的本質 1. 角色不同 2. 技術架構 三、功能特性&…

視覺對象類型

矩形類型 對于最基本的視覺效果,Qt Quick 提供了一種繪制矩形的類型。這些矩形可以用顏色或垂直漸變著色。該類型還可以在矩形上繪制邊框。 若要繪制矩形以外的自定義形狀,請參閱類型或使用該類型顯示預渲染圖像。 import QtQuickItem {width: 320h