-- ============================================================= -- 统一认证中心(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`);