做统一认证登录

This commit is contained in:
2026-09-19 21:44:04 +08:00
parent 1a4471e34d
commit fa281363fb
78 changed files with 8127 additions and 1442 deletions
+258
View File
@@ -0,0 +1,258 @@
-- =============================================================
-- 统一认证中心(UAC)表结构 数据库:go-platform
-- 路径:api.yunzer.cn/auth
--
-- 设计要点:
-- 1. yz_auth_identity 为「自然人」层,密码上提到这一层;
-- 2. yz_auth_tenant_user 为「身份-企业」绑定,一人可在多家企业任职;
-- 3. 密码列存 PHC 格式($argon2id$...),盐内联,无需独立 salt 列;
-- 历史数据为 salt$sha256(legacy),首次登录时自动升级;
-- 4. 会话/刷新令牌/授权码均存哈希,明文不下发到数据库;
-- 5. 本脚本只建表不写数据,数据迁移由 scripts/migrate_auth.go 完成。
-- =============================================================
SET NAMES utf8mb4;
-- ---------------- 1. 统一身份(自然人) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_identity` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '身份ID',
`union_id` VARCHAR(32) NOT NULL COMMENT '全局唯一标识(32位随机串)',
`mobile` VARCHAR(20) DEFAULT NULL COMMENT '手机号,全局唯一',
`email` VARCHAR(128) DEFAULT NULL COMMENT '邮箱,全局唯一',
`password_algo` VARCHAR(16) NOT NULL DEFAULT 'argon2id' COMMENT 'argon2id/legacy',
`password_hash` VARCHAR(255) DEFAULT NULL COMMENT 'PHC格式,含盐与参数',
`password_ver` INT NOT NULL DEFAULT 1 COMMENT '密码版本,改密时+1用于踢下线',
`nickname` VARCHAR(64) DEFAULT NULL,
`avatar` VARCHAR(500) DEFAULT NULL,
`mfa_enabled` TINYINT NOT NULL DEFAULT 0 COMMENT '是否开启二次验证',
`mfa_secret` VARCHAR(128) DEFAULT NULL COMMENT 'TOTP密钥(加密存储)',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '1启用/0禁用/2锁定',
`fail_count` INT NOT NULL DEFAULT 0 COMMENT '连续失败次数',
`locked_until` DATETIME DEFAULT NULL COMMENT '锁定截止时间',
`last_login_at` DATETIME DEFAULT NULL,
`last_login_ip` VARCHAR(45) DEFAULT NULL,
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`delete_time` DATETIME DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_union_id` (`union_id`),
UNIQUE KEY `uk_mobile` (`mobile`),
UNIQUE KEY `uk_email` (`email`),
KEY `idx_status` (`status`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-身份表';
-- ---------------- 2. 身份-企业绑定(一人多企) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_tenant_user` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`tid` BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
`identity_id` BIGINT UNSIGNED NOT NULL COMMENT '身份ID',
`account` VARCHAR(64) DEFAULT NULL COMMENT '企业内账号,可空(用手机号登录)',
`name` VARCHAR(64) DEFAULT NULL COMMENT '在该企业的姓名',
`phone` VARCHAR(20) DEFAULT NULL,
`email` VARCHAR(128) DEFAULT NULL,
`group_id` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '角色ID(cid=2的租户角色)',
`org_id` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '部门ID',
`is_default` TINYINT NOT NULL DEFAULT 0 COMMENT '是否默认企业',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '1启用/0禁用',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`delete_time` DATETIME DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tid_identity` (`tid`, `identity_id`),
KEY `idx_identity` (`identity_id`),
KEY `idx_tid_account` (`tid`, `account`),
KEY `idx_tid_status` (`tid`, `status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-身份企业绑定';
-- ---------------- 3. 接入应用(OIDC Client) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_client` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`client_id` VARCHAR(64) NOT NULL,
`client_secret` VARCHAR(128) DEFAULT NULL COMMENT '机密客户端才有,存哈希',
`app_code` VARCHAR(32) NOT NULL COMMENT 'crm/oa/uniapp/website...',
`name` VARCHAR(128) NOT NULL,
`app_type` TINYINT NOT NULL DEFAULT 1 COMMENT '1Web后端 2SPA 3原生APP 4小程序',
`redirect_uris` TEXT COMMENT 'JSON数组,精确匹配白名单',
`post_logout_uris` TEXT COMMENT '登出后允许回跳的地址',
`backchannel_logout_uri` VARCHAR(500) DEFAULT NULL COMMENT '单点登出回调(服务端通知)',
`grant_types` VARCHAR(255) NOT NULL DEFAULT 'authorization_code,refresh_token',
`scope` VARCHAR(255) DEFAULT 'openid,profile,tenant',
`access_ttl` INT NOT NULL DEFAULT 1800 COMMENT '访问令牌有效期(秒)',
`refresh_ttl` INT NOT NULL DEFAULT 2592000 COMMENT '刷新令牌有效期(秒)',
`realm` VARCHAR(16) NOT NULL DEFAULT 'tenant' COMMENT 'tenant/platform',
`status` TINYINT NOT NULL DEFAULT 1,
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_client_id` (`client_id`),
UNIQUE KEY `uk_app_code` (`app_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-接入应用';
-- ---------------- 4. 登录会话(1号1机 / 强制下线) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_session` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`sid` VARCHAR(64) NOT NULL COMMENT '会话ID,写入JWT的sid',
`identity_id` BIGINT UNSIGNED NOT NULL,
`tid` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '当前所选企业',
`client_id` VARCHAR(64) NOT NULL DEFAULT '',
`device_id` VARCHAR(64) DEFAULT NULL,
`device_name` VARCHAR(128) DEFAULT NULL,
`ip` VARCHAR(45) DEFAULT NULL,
`user_agent` VARCHAR(500) DEFAULT NULL,
`login_type` VARCHAR(20) NOT NULL DEFAULT 'password',
`amr` VARCHAR(64) DEFAULT NULL COMMENT 'pwd/sms/otp/wx/dingtalk/feishu/qq/github/google',
`login_at` DATETIME NOT NULL,
`last_access_at` DATETIME NOT NULL,
`expires_at` DATETIME NOT NULL,
`revoked` TINYINT NOT NULL DEFAULT 0,
`revoke_reason` VARCHAR(64) DEFAULT NULL COMMENT 'logout/kicked/admin/expired',
`revoke_at` DATETIME DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sid` (`sid`),
KEY `idx_identity_status` (`identity_id`, `revoked`),
KEY `idx_tid` (`tid`),
KEY `idx_expires` (`expires_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-登录会话';
-- ---------------- 5. 刷新令牌(轮换 + 重放检测) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_refresh_token` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`token_hash` VARCHAR(128) NOT NULL COMMENT '不透明串的哈希,明文不下发落库',
`identity_id` BIGINT UNSIGNED NOT NULL,
`tid` BIGINT UNSIGNED NOT NULL DEFAULT 0,
`client_id` VARCHAR(64) NOT NULL DEFAULT '',
`sid` VARCHAR(64) NOT NULL DEFAULT '',
`family_id` VARCHAR(64) NOT NULL COMMENT '轮换家族,检测到重放则整族吊销',
`rotated_from` VARCHAR(128) DEFAULT NULL,
`used` TINYINT NOT NULL DEFAULT 0,
`revoked` TINYINT NOT NULL DEFAULT 0,
`expires_at` DATETIME NOT NULL,
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_token_hash` (`token_hash`),
KEY `idx_family` (`family_id`),
KEY `idx_identity` (`identity_id`),
KEY `idx_expires` (`expires_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-刷新令牌';
-- ---------------- 6. 授权码(一次性,60秒) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_code` (
`code_hash` VARCHAR(128) NOT NULL COMMENT '授权码哈希',
`client_id` VARCHAR(64) NOT NULL,
`identity_id` BIGINT UNSIGNED NOT NULL,
`tid` BIGINT UNSIGNED NOT NULL DEFAULT 0,
`redirect_uri` VARCHAR(500) NOT NULL,
`code_challenge` VARCHAR(128) NOT NULL COMMENT 'PKCE',
`code_challenge_method` VARCHAR(10) NOT NULL DEFAULT 'S256',
`scope` VARCHAR(255) DEFAULT NULL,
`nonce` VARCHAR(128) DEFAULT NULL COMMENT 'OIDC nonce,进ID Token',
`used` TINYINT NOT NULL DEFAULT 0,
`expires_at` DATETIME NOT NULL,
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`code_hash`),
KEY `idx_expires` (`expires_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-授权码';
-- ---------------- 7. 令牌吊销表(登出/踢下线) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_token_blacklist` (
`jti` VARCHAR(64) NOT NULL COMMENT 'JWT ID',
`identity_id` BIGINT UNSIGNED NOT NULL DEFAULT 0,
`sid` VARCHAR(64) DEFAULT NULL,
`reason` VARCHAR(64) DEFAULT NULL,
`expires_at` DATETIME NOT NULL COMMENT '原token过期时间,到期后可清理',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`jti`),
KEY `idx_expires` (`expires_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-令牌吊销表';
-- ---------------- 8. 第三方身份绑定 ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_identity_third` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`identity_id` BIGINT UNSIGNED NOT NULL,
`provider` VARCHAR(32) NOT NULL COMMENT 'wechat/dingtalk/feishu/qq/github/google',
`open_id` VARCHAR(128) NOT NULL COMMENT '该平台内的唯一ID',
`union_id` VARCHAR(128) DEFAULT NULL COMMENT '跨平台唯一ID(微信/钉钉有)',
`nickname` VARCHAR(128) DEFAULT NULL,
`avatar` VARCHAR(500) DEFAULT NULL,
`raw` TEXT COMMENT '原始用户信息JSON',
`bind_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_provider_open` (`provider`, `open_id`),
KEY `idx_identity` (`identity_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-第三方绑定';
-- ---------------- 9. 租户自带身份源(企业微信/钉钉/飞书/OIDC) ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_tenant_idp` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`tid` BIGINT UNSIGNED NOT NULL,
`provider` VARCHAR(32) NOT NULL COMMENT 'dingtalk/feishu/wework/oidc/saml',
`name` VARCHAR(128) DEFAULT NULL COMMENT '显示名称',
`app_id` VARCHAR(128) DEFAULT NULL,
`app_secret` VARCHAR(512) DEFAULT NULL COMMENT '加密存储',
`issuer` VARCHAR(500) DEFAULT NULL COMMENT 'OIDC/SAML issuer',
`auth_url` VARCHAR(500) DEFAULT NULL,
`token_url` VARCHAR(500) DEFAULT NULL,
`userinfo_url` VARCHAR(500) DEFAULT NULL,
`jwks_url` VARCHAR(500) DEFAULT NULL,
`scopes` VARCHAR(255) DEFAULT NULL,
`attr_map` TEXT COMMENT 'JSON:字段映射(手机/姓名/部门)',
`proxy_url` VARCHAR(500) DEFAULT NULL COMMENT 'GitHub/Google等需要代理时填写',
`status` TINYINT NOT NULL DEFAULT 1,
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_tid_provider` (`tid`, `provider`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-租户身份源';
-- ---------------- 10. 租户登录策略 ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_tenant_auth_config` (
`tid` BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
`verify_type` VARCHAR(20) NOT NULL DEFAULT 'captcha' COMMENT 'none/captcha/sms/email/geetest',
`open_verify` TINYINT NOT NULL DEFAULT 1 COMMENT '是否开启登录二次验证',
`pwd_min_len` INT NOT NULL DEFAULT 8,
`pwd_complexity` TINYINT NOT NULL DEFAULT 0 COMMENT '0不限制 1字母+数字 2大小写+数字+符号',
`session_ttl` INT NOT NULL DEFAULT 7200 COMMENT '会话有效期(秒)',
`max_session` INT NOT NULL DEFAULT 1 COMMENT '同账号最大同时在线数(默认1号1机)',
`kick_strategy` TINYINT NOT NULL DEFAULT 1 COMMENT '1踢掉旧会话 2拒绝新登录',
`mfa_required` TINYINT NOT NULL DEFAULT 0,
`ip_whitelist` TEXT COMMENT 'JSON数组,为空表示不限制',
`allow_third` VARCHAR(255) DEFAULT NULL COMMENT '允许的第三方登录,逗号分隔,空表示全部',
`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`tid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-租户登录策略';
-- ---------------- 11. 统一登录日志 ----------------
CREATE TABLE IF NOT EXISTS `yz_auth_login_log` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`tid` BIGINT UNSIGNED DEFAULT NULL,
`identity_id` BIGINT UNSIGNED DEFAULT NULL,
`account` VARCHAR(64) NOT NULL DEFAULT '',
`user_name` VARCHAR(64) NOT NULL DEFAULT '',
`tenant_name` VARCHAR(64) NOT NULL DEFAULT '',
`client_id` VARCHAR(64) NOT NULL DEFAULT '',
`login_type` VARCHAR(20) NOT NULL DEFAULT 'password' COMMENT 'password/sms/otp/third',
`amr` VARCHAR(64) DEFAULT NULL,
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '1成功/0失败',
`message` VARCHAR(255) NOT NULL DEFAULT '',
`ip` VARCHAR(45) NOT NULL DEFAULT '',
`user_agent` VARCHAR(500) NOT NULL DEFAULT '',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_tid` (`tid`),
KEY `idx_identity` (`identity_id`),
KEY `idx_account` (`account`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='统一认证-登录日志';
-- =============================================================
-- 内置接入应用(后续由 platform 端「应用注册」页面维护)
-- client_secret 为占位值,正式启用前必须在管理端重新生成
-- =============================================================
INSERT INTO `yz_auth_client`
(`client_id`, `app_code`, `name`, `app_type`, `grant_types`, `scope`, `access_ttl`, `refresh_ttl`, `realm`)
VALUES
('yz-backend', 'backend', '租户管理后台', 2, 'authorization_code,refresh_token', 'openid,profile,tenant', 1800, 2592000, 'tenant'),
('yz-uniapp', 'uniapp', '移动端APP', 3, 'authorization_code,refresh_token', 'openid,profile,tenant', 1800, 2592000, 'tenant'),
('yz-website', 'website', '企业官网', 2, 'authorization_code,refresh_token', 'openid,profile,tenant', 1800, 2592000, 'tenant')
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`);