UM v1.1 引入了三级权限 + 6 大登录策略 + 灵活配置中心,解决 B 端商家入驻场景下"单点登录 vs 独立登录"的灵活配置问题。
yunjii),同组应用共享登录态um_perm_registry,新增策略无需改代码| 策略 | 标识 | 适用场景 |
|---|---|---|
| 独立登录 | independent |
敏感应用、支付系统。每个 app 独立鉴权。 |
| 分组 SSO | group_sso |
自营产品线、商家多应用。同组共享登录态。 |
| 全局 SSO | global_sso |
企业内部系统、单一品牌全线产品。登录即全平台免登。 |
| 单设备登录 | single_device |
交易系统、VIP 内容平台。同时仅 1 个设备在线。 |
| 多设备限额 | multi_device |
SaaS 工具。允许 N 个设备同时在线,0=不限制。 |
| IP 绑定 | ip_bound |
后台管理系统、高安全场景。IP 变化需重新认证。 |
app_scope + group_scope 内应用um_user_preference 表达个人偏好
um_b_roles)| 角色 | 代码 | 权限规则 |
|---|---|---|
| 超级管理员 | super_admin |
{"*":"*"} 全部 |
| 客户管理员 | customer |
{"policy_option":"rw","app_field":"rw"} |
| 商家 | merchant |
{"policy_option":"rw","app_field":"r","own_apps":"rw"} |
| 加盟商 | franchise |
同 merchant,可配子账号 |
| 代理商 | agent |
{"policy_option":"r","app_field":"r"} 只读+统计 |
| 只读运营 | readonly |
{"*":"r"} |
ConfigCenter)核心所有可配置项必须在 um_perm_registry 中注册。配置合并优先级:
应用级 override > 分组级 override > perm_registry 默认值
| perm_key | 类型 | 默认 | 范围 | B端 |
|---|---|---|---|---|
| 📦 策略开关(6 项) | ||||
policy.independent.allow |
bool | 1 | - | ✓ |
policy.group_sso.allow |
bool | 1 | - | ✓ |
policy.global_sso.allow |
bool | 1 | - | ✓ |
policy.single_device.allow |
bool | 1 | - | ✓ |
policy.multi_device.allow |
bool | 1 | - | ✓ |
policy.ip_bound.allow |
bool | 1 | - | ✓ |
| 🔧 策略子选项(6 项) | ||||
multi_device.max_devices |
int | 0 | 0~999 | ✓ |
single_device.kick_mode |
enum | kick_old | kick_old/reject_new | ✓ |
ip_bound.change_action |
enum | kick | kick/warn/force_relogin | ✓ |
ip_bound.check_interval |
int | 60 | 10~3600 | ✓ |
group_sso.cookie_domain |
string | .yunjii.cn | - | 仅客户 |
group_sso.cookie_ttl |
int | 604800 | 60~2592000 | 仅客户 |
| 🔐 通用登录配置(7 项) | ||||
login.max_attempts |
int | 5 | 0~999 | ✓ |
login.lock_minutes |
int | 30 | 0~9999 | ✓ |
login.session_timeout |
int | 0 | 0~86400 | ✓ |
login.allow_simultaneous |
bool | 1 | - | ✓ |
login.password_min_length |
int | 6 | 4~32 | ✓ |
login.password_complex |
enum | letter_digit | any/letter_digit/strong | ✓ |
independent.need_captcha |
bool | 0 | - | ✓ |
| 📱 应用级配置(8 项) | ||||
app.allow_register |
bool | 1 | - | ✓ |
app.allow_oauth |
bool | 1 | - | ✓ |
app.allow_phone_login |
bool | 1 | - | ✓ |
app.allow_email_login |
bool | 1 | - | ✓ |
app.allow_password_login |
bool | 1 | - | ✓ |
app.allow_sms_code_login |
bool | 1 | - | ✓ |
app.token_expire_hours |
int | 168 | 1~8760 | ✓ |
app.show_in_user_center |
bool | 1 | - | ✓ |
um_perm_registry INSERT 一行即可,B 端商家控制台和客户后台会自动显示该选项。
act=check_sso - SSO 状态检测检测用户是否已在 SSO 中心登录。已登录直接返回 Token。
成功响应:
{
"code": 0,
"logged_in": true,
"token": "eyJ0eXAiOiJKV1Qi...",
"scope": "yunjii",
"scope_type": "group",
"user": { "id": 10086, "nickname": "demo" }
}
act=sso_logout - SSO 统一登出登出当前作用域内所有 Token(单设备/分组/全局)。
act=policy - 查询应用登录策略供前端 SDK 动态获取当前应用的策略配置。
{
"code": 0,
"policy": "group_sso",
"group_key": "yunjii",
"all_options": {
"multi_device.max_devices": 0,
"login.max_attempts": 5,
"ip_bound.change_action": "kick",
...
}
}
从 v1 单 Token 升级为 v2 多实例:um_user_token 表存储按 scope 分组的多 Token。
| 字段 | 说明 |
|---|---|
scope |
作用域:global / group_xxx / app_xxx |
scope_type |
global / group / app |
device_id |
设备指纹(single/multi_device 必填) |
login_ip |
登录 IP(ip_bound 必填) |
ip_bound |
是否 IP 绑定 |
expire_at |
过期时间 |
um_user_token 表是否存在;不存在则回退到 v1(um_user.token 单字段)。
DeviceFingerprint::generate() 基于 UA + IP + Accept-Language 生成设备 ID。
um_user_device 表记录每个设备的登录信息:
C 端用户可以在"我的设备"页面查看并主动踢出某个设备。
| 表名 | 说明 |
|---|---|
um_app_group |
应用分组(含 owner_id/scope_type) |
um_app_group_rel |
应用↔分组关联(多对多) |
um_user_token |
Token 多实例表(v2 核心) |
um_user_device |
用户设备记录 |
um_b_users |
B 端用户(商家/加盟商/代理商) |
um_b_roles |
B 端角色模板(已预置 6 个) |
um_perm_registry |
权限注册表(27+ 项可配置) |
um_config_override |
配置项覆盖表(应用/分组级别) |
um_login_attempt |
登录尝试记录(用于锁定/限流) |
um_user_preference |
C 端用户偏好 |
um/auth.php)| 类 | 职责 |
|---|---|
LoginPolicy |
策略枚举 + 描述 + needsGroup/needsDevice/needsIpBound 判断 |
Token |
JWT 编码/解码 + v1/v2 兼容 + 多策略 Token 生成与验证 |
PolicyResolver |
根据 appid 解析最终策略:app > group > registry 默认 |
DeviceFingerprint |
设备指纹生成与解析 |
BUserAuth |
B 端登录态管理 + 权限判断 can() / ownsApp() / ownsGroup() |
ConfigCenter |
注册表加载 + override 合并 + 值校验 |
| 入口 | URL | 用途 |
|---|---|---|
| 管理员后台 - 应用管理 | /um/admin/apps.php |
创建/编辑应用、设置分组、覆盖策略 |
| 管理员后台 - 应用分组 | /um/admin/groups.php |
管理分组、设置分组级策略 |
| 管理员后台 - B 端用户 | /um/admin/b_users.php |
创建商家账号、分配 app_scope/group_scope |
| 管理员后台 - 权限注册表 | /um/admin/registry.php |
查看/调整每个配置项的 B 端可改/只读 |
| B 端商家控制台 | /um/b_console.php |
商家登录后配置自己的应用策略 |
| B 端登录入口 | /um/b_login.php |
商家账号登录 |
// 在管理后台创建分组
INSERT INTO um_app_group (group_key, name, login_policy, policy_config)
VALUES ('yunjii', '云集产品线', 'group_sso', '{"max_devices":0}');
// 把多个 app 加入分组
UPDATE um_apps SET group_id=2 WHERE appid IN (1001, 1002, 1003, 1005);
// 效果:用户登录任意一个 app,同分组所有 app 自动登录
// 设备数无限制(max_devices=0)
// Cookie 域:.yunjii.cn(主域下所有子域共享)
// 创建分组 "trading"
INSERT INTO um_app_group (group_key, name, login_policy, policy_config)
VALUES ('trading', '交易系统', 'single_device', '{}');
// 应用表覆盖策略(再叠加 IP 绑定)
UPDATE um_apps SET login_policy='ip_bound' WHERE appid=2001;
// policy_config: {"ip_bound":true,"change_action":"kick"}
// 效果:
// 1. 用户在新设备登录,旧设备立即被踢
// 2. IP 变化立即踢出,需重新登录
// B 端商家在控制台里调整 max_devices = 3
$cc = new ConfigCenter();
$cc->set('multi_device.max_devices', 3, appid: 3001, bUserId: 5);
// 效果:用户最多 3 个设备同时在线
// 第 4 个设备登录时,自动踢出最早的第 1 个
require_once 'auth.php';
$token = new Token();
$result = $token->generateWithPolicy(
userId: 10086,
openid: 'oxxx',
type: 'wx',
appid: 1001,
options: [
'policy' => 'group_sso',
'group_key' => 'yunjii',
'device_id' => DeviceFingerprint::generate(),
'device_info' => DeviceFingerprint::info(),
'max_devices' => 0, // 0 = 不限制
'ip_bound' => true, // 强 IP 绑定
]
);
$cc = new ConfigCenter();
$opts = $cc->getEffective(1001);
echo $opts['multi_device.max_devices']; // 0
echo $opts['login.max_attempts']; // 5
echo $opts['ip_bound.change_action']; // 'kick'
$bAuth = new BUserAuth();
if ($bAuth->can('multi_device.max_devices', 'w')) {
// 当前 B 端用户可修改最大设备数
}
if ($bAuth->ownsApp(1001)) {
// 当前 B 端用户管辖 appid=1001
}
um/migrate_sso.sql 创建 3 张表 + 2 个 ALTERum/migrate_rbac.sql 创建 6 张表 + 1 个存储过程 + 27 项配置注册