内容纲要
1. 概述
使用 Guardian Client 的 Java API,可以批量创建用户并授予权限,避免在 Guardian 界面上逐个手工操作。
本文提供一段已在 TDH 集群实测通过的完整代码:创建一批用户 → 授 GLOBAL ADMIN 权限 → 授表级 INSERT 权限 → 自动验证结果。脚本支持重复执行(已存在的用户自动跳过)。
2. 官方 Demo 简介
官方 demo 工程( guardian-demo 下载链接)包含两个模块,本文示例基于其中的 guardian-client-demo:
| 模块 / 样例类 | 功能 |
|---|---|
| guardian-client-demo | Guardian Client API 使用示例(本文内容) |
| guardian-migration-demo | 将旧版 Guardian(ApacheDS)数据迁移至数据库的工具 |
guardian-client-demo 提供三个样例类,覆盖最常见的三类操作:
| 样例类 | 功能 | 核心方法 |
|---|---|---|
| UserDemo | 用户全生命周期管理 | addUser 创建用户、updateUserPassword 修改密码(用户只能改自己的)、assign/deassign 加入或移出组/角色、createAccessToken/deleteAccessToken 管理 Access Token |
| UserPermissionDemo | 服务权限管理 | grant/revoke 赋权撤权、userPermissions 查询权限(含继承)、checkAccess 鉴权检查、getEffectiveService 获取有效服务名 |
| QuotaDemo | 配额管理 | addQuota/updateQuota/deleteQuota 管理数据库存储配额、临时空间配额和 Furion 调度队列配额 |
官方 demo 的两种用法:
- 直接跑样例:配置好 guardian-site.xml 后,运行各 Demo 的 main 方法即可体验完整流程(如 UserDemo 会依次执行创建→改密→赋权→查询→删除的演示,最后把演示用户删掉)。
- 改造复用:把样例中的 API 调用抽取出来组装成自己的业务代码——本文第 4 节的批量脚本就是基于 UserDemo(创建用户)和 UserPermissionDemo(赋权)改写的。
3. 环境准备
- JDK 1.8 及以上
- 能访问 Guardian Server(默认端口
8380) - 一套具有用户管理权限的管理员账号(如
admin)
依赖 jar 包:
引用集群客户端目录 (推荐,最简单):TDH 客户端目录(如 /root/TDH-Client/inceptor/lib/)已包含全部依赖,编译运行时用通配符整目录引入即可,无需关心 jar 清单。
4. 配置文件 guardian-site.xml
连接参数(Server 地址、账号密码)统一放在 guardian-site.xml 配置文件中,与代码分离,换环境只改配置、不动代码。
在代码同级目录下创建 conf 目录,将配置文件放在 conf/guardian-site.xml:
guardian.server.address
172.18.131.172:8380;172.18.131.173:8380
guardian.server.tls.enabled
true
guardian.connection.username
admin
guardian.connection.password
123456
目录结构:
guardian_task/ ├── conf/ │ └── guardian-site.xml <- 连接配置,按环境修改 └── GuardianBatchDemo.java <- 业务代码,无需改动
4. 批量创建用户并赋权(完整代码)
举例说明,创建user1/user2/user3这3个用户,并且赋权对quark1服务GLOBAL级的ADMIN权限,以及对default.emp_holo包的insert权限。
保存为 GuardianBatchDemo.java,只修改开头 5 个参数(用户清单、密码、服务名、库、表):
import io.transwarp.guardian.client.GuardianAdmin;
import io.transwarp.guardian.client.GuardianAdminFactory;
import io.transwarp.guardian.client.GuardianClient;
import io.transwarp.guardian.client.GuardianClientFactory;
import io.transwarp.guardian.common.model.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class GuardianBatchDemo {
// ===== 1. 批量任务清单:按需增删用户名即可 =====
static String[] USERS = {"user1", "user2", "user3"};
static String PASSWORD = "123456"; // 需符合集群密码策略
static String SERVICE = "quark1"; // 目标服务名
static String DB = "default";
static String TABLE = "emp_holo";
public static void main(String[] args) throws Exception {
// ===== 2. 连接 Guardian:无参工厂,自动读取 classpath 下的 guardian-site.xml =====
GuardianClient client = GuardianClientFactory.getInstance();
GuardianAdmin admin = GuardianAdminFactory.getInstance();
System.out.println("[OK] connected via guardian-site.xml");
// ===== 3. 批量执行:创建用户 + 赋权 =====
for (String user : USERS) {
System.out.println("---- 处理用户 " + user + " ----");
createUser(client, admin, user);
grant(admin, user, Collections.singletonList("GLOBAL"), "ADMIN");
grant(admin, user, Arrays.asList("TABLE_OR_VIEW", DB, TABLE), "INSERT");
}
// ===== 4. 批量验证 =====
System.out.println("===== 权限验证结果 =====");
for (String user : USERS) {
boolean globalAdmin = client.checkAccess(user,
new PermissionVo(SERVICE, Collections.singletonList("GLOBAL"), "ADMIN"));
boolean tableInsert = client.checkAccess(user,
new PermissionVo(SERVICE, Arrays.asList("TABLE_OR_VIEW", DB, TABLE), "INSERT"));
System.out.println(user + " : GLOBAL ADMIN=" + globalAdmin + ", INSERT=" + tableInsert);
}
}
// 创建用户;已存在则跳过(保证脚本可重复执行)
static void createUser(GuardianClient client, GuardianAdmin admin, String user) throws Exception {
try {
client.getUser(user); // 能查到说明已存在
System.out.println("[跳过] 用户 " + user + " 已存在");
return;
} catch (Exception e) {
// 查询失败 = 用户不存在,继续创建
}
UserVo vo = new UserVo(user);
vo.setUserPassword(PASSWORD);
vo.setUserDescription("batch created by guardian client");
admin.addUser(vo);
System.out.println("[创建] 用户 " + user + " 创建成功");
}
// 单条赋权:path 为资源路径,action 为动作(全大写)
static void grant(GuardianAdmin admin, String user, List path, String action) {
try {
admin.grant(EntityPermissionVo.UserPerm(user, new PermissionVo(SERVICE, path, action)));
System.out.println("[赋权] " + user + " <- " + path + " " + action);
} catch (Exception e) {
System.out.println("[告警] " + user + " 赋权 " + action + " 失败(可能已存在): " + e.getMessage());
}
}
}
代码结构说明:
| 部分 | 作用 |
|---|---|
| 参数区(第 1 段) | 用户清单、统一密码、目标服务/库/表,全部集中在这里修改 |
| 连接区(第 2 段) | 无参工厂 getInstance(),自动加载 guardian-site.xml,代码内无地址密码 |
| 批量执行(第 3 段) | 循环每个用户:先创建,再依次授予两条权限 |
| 批量验证(第 4 段) | 循环用 checkAccess 回读,输出 true/false |
5. 编译与运行
实测输出示例(首轮执行):
[OK] connected via guardian-site.xml
---- 处理用户 user1 ----
[创建] 用户 user1 创建成功
[赋权] user1 <- [GLOBAL] ADMIN
[赋权] user1 <- [TABLE_OR_VIEW, default, emp_holo] INSERT
---- 处理用户 user2 ----
...
===== 权限验证结果 =====
user1 : GLOBAL ADMIN=true, INSERT=true
user2 : GLOBAL ADMIN=true, INSERT=true
user3 : GLOBAL ADMIN=true, INSERT=true
重复执行时,已存在的用户会输出 [跳过] 用户 xxx 已存在,不会报错中断,权限重复授予无副作用。
6. 常见调整场景
| 需求 | 修改方法 |
|---|---|
| 增减用户数量 | 修改 USERS 数组即可 |
| 每个用户不同密码 | 去掉 PASSWORD 常量,改用 Map<String, String> 存放 用户名→密码 |
| 授权到整个库 | 把路径换成 Arrays.asList("DATABASE", "库名") |
| 授权到其他服务 | 修改 SERVICE,如 inceptor1、argodbstorage |
| 换权限动作 | 修改 action 参数,如 SELECT、UPDATE、DELETE(必须全大写) |
| 批量撤销权限 | 把 grant(...) 换成同参数的 admin.revoke(...) |
| 更换集群环境 | 只改 conf/guardian-site.xml,代码不动 |