新增了登录失败次数统计和临时锁定机制,包括: 1. 定义登录锁定数据结构和数据库表结构 2. 实现租户级别的锁定状态持久化接口 3. 添加登录速率限制安全策略配置 4. 在登录流程中加入锁定前置检查和失败计数逻辑 5. 提供管理员手动解锁的内部API接口 6. 新增中文本地化的锁定提示文案
84 lines
5.4 KiB
Go
84 lines
5.4 KiB
Go
//go:build mysql
|
|
// +build mysql
|
|
|
|
package mysql
|
|
|
|
func ensureIMAdminGovernanceTables(exec sqlExecutor) error {
|
|
statements := []string{
|
|
`CREATE TABLE IF NOT EXISTS im_user_login_logs (
|
|
id BIGINT NOT NULL AUTO_INCREMENT, user_id BIGINT NOT NULL,
|
|
username VARCHAR(64) NOT NULL DEFAULT '', account_type VARCHAR(24) NOT NULL DEFAULT '',
|
|
account_hash CHAR(64) NOT NULL DEFAULT '', account_mask VARCHAR(128) NOT NULL DEFAULT '',
|
|
login_type VARCHAR(24) NOT NULL, event_type VARCHAR(24) NOT NULL DEFAULT 'login',
|
|
session_id VARCHAR(96) NOT NULL DEFAULT '', device_id VARCHAR(255) NOT NULL DEFAULT '',
|
|
platform VARCHAR(32) NOT NULL DEFAULT 'unknown', app_version VARCHAR(32) NOT NULL DEFAULT '',
|
|
ip VARCHAR(64) NOT NULL DEFAULT '', region VARCHAR(128) NOT NULL DEFAULT '',
|
|
user_agent VARCHAR(512) NOT NULL DEFAULT '', risk_level VARCHAR(16) NOT NULL DEFAULT 'low',
|
|
request_id VARCHAR(64) NOT NULL DEFAULT '', login_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
logout_at DATETIME(3), metadata JSON, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY(id), INDEX idx_im_user_login_user_time(user_id, login_at DESC, id DESC),
|
|
INDEX idx_im_user_login_ip_time(ip, login_at DESC, id DESC),
|
|
INDEX idx_im_user_login_device_time(device_id(64), login_at DESC),
|
|
INDEX idx_im_user_login_request(request_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`,
|
|
`CREATE TABLE IF NOT EXISTS im_login_failure_logs (
|
|
id BIGINT NOT NULL AUTO_INCREMENT, user_id BIGINT,
|
|
account_type VARCHAR(24) NOT NULL DEFAULT '', account_hash CHAR(64) NOT NULL DEFAULT '',
|
|
account_mask VARCHAR(128) NOT NULL DEFAULT '', failure_type VARCHAR(32) NOT NULL,
|
|
reason VARCHAR(96) NOT NULL DEFAULT '', detail VARCHAR(500) NOT NULL DEFAULT '',
|
|
ip VARCHAR(64) NOT NULL DEFAULT '', region VARCHAR(128) NOT NULL DEFAULT '',
|
|
device_id VARCHAR(255) NOT NULL DEFAULT '', platform VARCHAR(32) NOT NULL DEFAULT 'unknown',
|
|
app_version VARCHAR(32) NOT NULL DEFAULT '', user_agent VARCHAR(512) NOT NULL DEFAULT '',
|
|
risk_level VARCHAR(16) NOT NULL DEFAULT 'medium', risk_action VARCHAR(24) NOT NULL DEFAULT 'audit_only',
|
|
request_id VARCHAR(64) NOT NULL DEFAULT '', attempt_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
metadata JSON, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY(id), INDEX idx_im_login_failure_account_time(account_hash, attempt_at DESC, id DESC),
|
|
INDEX idx_im_login_failure_user_time(user_id, attempt_at DESC, id DESC),
|
|
INDEX idx_im_login_failure_ip_time(ip, attempt_at DESC, id DESC),
|
|
INDEX idx_im_login_failure_type_time(failure_type, attempt_at DESC, id DESC),
|
|
INDEX idx_im_login_failure_request(request_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`,
|
|
`CREATE TABLE IF NOT EXISTS im_login_lockouts (
|
|
id BIGINT NOT NULL, user_id BIGINT,
|
|
account_hash CHAR(64) NOT NULL,
|
|
failed_attempts INT NOT NULL DEFAULT 0,
|
|
window_started_at DATETIME(3), locked_until DATETIME(3), last_attempt_at DATETIME(3),
|
|
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY(id), UNIQUE INDEX uk_im_login_lockouts_account(account_hash),
|
|
INDEX idx_im_login_lockouts_user(user_id), INDEX idx_im_login_lockouts_locked(locked_until)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`,
|
|
`CREATE TABLE IF NOT EXISTS im_message_admin_actions (
|
|
id BIGINT NOT NULL AUTO_INCREMENT, action_id VARCHAR(96) NOT NULL,
|
|
command_id VARCHAR(96) NOT NULL, conversation_type VARCHAR(16) NOT NULL,
|
|
topic VARCHAR(64) NOT NULL, seqid BIGINT NOT NULL, sender_user_id BIGINT,
|
|
action VARCHAR(16) NOT NULL, action_status VARCHAR(16) NOT NULL DEFAULT 'pending',
|
|
reason VARCHAR(500) NOT NULL DEFAULT '', actor_admin_id BIGINT NOT NULL DEFAULT 0,
|
|
request_id VARCHAR(64) NOT NULL DEFAULT '', before_snapshot JSON, after_snapshot JSON,
|
|
failure_reason VARCHAR(96) NOT NULL DEFAULT '', failure_message VARCHAR(1000) NOT NULL DEFAULT '',
|
|
processed_at DATETIME(3), created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY(id), UNIQUE INDEX uk_im_message_admin_action_id(action_id),
|
|
UNIQUE INDEX uk_im_message_admin_command(command_id),
|
|
INDEX idx_im_message_admin_target(conversation_type, topic, seqid, id DESC),
|
|
INDEX idx_im_message_admin_status(action_status, created_at, id),
|
|
INDEX idx_im_message_admin_actor(actor_admin_id, created_at DESC)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`,
|
|
`CREATE TABLE IF NOT EXISTS im_user_ip_whitelists (
|
|
id BIGINT NOT NULL AUTO_INCREMENT, user_id BIGINT NOT NULL,
|
|
ip_cidr VARCHAR(64) NOT NULL, status TINYINT NOT NULL DEFAULT 1,
|
|
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), created_by BIGINT NOT NULL DEFAULT 0,
|
|
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), updated_by BIGINT NOT NULL DEFAULT 0,
|
|
deleted_at DATETIME(3), deleted_by BIGINT,
|
|
PRIMARY KEY(id), UNIQUE INDEX uk_im_user_ip_whitelist(user_id,ip_cidr),
|
|
INDEX idx_im_user_ip_whitelist_user(user_id,status), INDEX idx_im_user_ip_whitelist_deleted(deleted_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`,
|
|
}
|
|
for _, statement := range statements {
|
|
if _, err := exec.Exec(statement); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|