配置用户提供商
配置用户提供程序无需复制和同步在记录系统 (SoR) 的身份提供程序配置设置中创建和维护的用户组,从而提高了管理效率。
微应用管理员可以将用户提供商配置为从 SoR 收集用户和用户组数据,并使用这些数据管理所有集成中的微应用订阅。要配置用户提供程序,您的应用程序 SoR 必须提供公开用户/用户组的 API,例如 ServiceNow、Salesforce、Jira 等。
创建用户提供商
您可以手动创建新的用户提供程序,也可以导入已配置的用户提供程序。
请按照以下步骤进行操作:
-
在 微应用集成 页面中,选择顶部栏中的 “ 用户提供商 ” 选项卡。
- 选择用户提供商类型。选择 从 HTTP Web 服务创建新的用户提供程序 以手动配置此用户提供程序。您还可以 导入以前配置的用户提供程序。有关导入的详细信息,请参阅 导入。
- 输入连接的 用户提供程序名称 。
- 输入用户提供商 基本 URL。
- 从 图标 库中为用户提供者选择一个图标,或将其保留为默认图标。
- 选择 服务身份验证 方法,然后根据您使用的身份验证方法填写所有必需的详细信息。有关身份验证方法的详细信息,请参阅 设置服务身份验证。
- (可选)根据需要 启用请求速率限制 开关,然后输入 请求数 和 时间间隔。
- (可选)如果需要,请输入 请求超时 的值。
-
选择 添加 以完成用户提供程序的创建。
现在你导入一个脚本来完成。
导入脚本
使用微应用中的用 户提供程序脚本 功能,您需要上传脚本才能完成用户提供程序设置。我们在下面提供了脚本要求和 JavaScript 模型。请参阅 准备脚本。有关脚本的一般信息,请参阅 HTTP 集成脚本。
添加用户提供程序后(在前面的过程中),页面将打开,其中包含用户提供程序的视图。请按照以下步骤添加脚本。
- 选择 状态 下的 添加脚本。
- 选择 导入脚本。
-
将脚本拖到导入弹出窗口中,或浏览查找文件。脚本必须是不大于 1 MB 的 .js 文件。
脚本经过解析和验证。
-
选择 导入 完成。
您可以在用户提供程序的 用户提供程序脚本视图中的脚本 处理程序下看到脚本详细信息。要查看脚本发出的请求,请选择用户提供程序条目旁边的菜单,然后选择 同步日志。
现在,在分配订阅者时,您的新用户提供商可用。有关详细信息,请参阅 管理订阅者。
准备你的脚本
准备脚本时,请考虑以下要求:
- 导入脚本必须从加载内置库微应用程序用户组开始。此库定义了必须存储在数据库中的对象:
const { User, Group, UserGroupMapping } = library.load("microapp-user-groups");
-
对象具有以下结构/属性:
-
User(accountName, displayName, email, domain, userPrincipalName, userId)
电子邮件地址在用户提供商内必须唯 -
Group(accountName, displayName, domain, userPrincipalName, groupId, parentGroupId)
组层次结构也可以使用 parentGroupID 进行定义 -
UserGroupMapping(userId, groupId)
将用户映射到组
-
- 所有属性都是数据类型
STRING
。 - 用户 .email 必须与登录到 Citrix Workspace 的用户的电子邮件匹配。
模型脚本
使用以下 JavaScript 代码作为模型。
注意
以下模型是专门为 ServiceNow SoR 编写的。此脚本与其他服务不兼容。
const { User, Group, UserGroupMapping } = library.load("microapp-user-groups");
function fullSync(params) {
fullSyncUsers(params);
fullSyncGroups(params);
fullSyncUserGroupMapping(params);
}
function fullSyncUsers({ client, dataStore }) {
let offset = 0;
do {
const response = client.fetchSync(
`/api/now/table/sys_user?sysparm_fields=sys_domain_path%2Cname%2C%20sys_id%2Cuser_name%2Cemail&sysparm_query=emailISNOTEMPTY^active%3Dtrue&sysparm_limit=100&sysparm_offset=${offset}`
);
if (!response.ok) {
console.log("Error status:", response.status, response.statusText);
console.log("Error body:", response.textSync());
throw new Error("Network response was not ok");
}
console.log("fetch done");
const users = response.jsonSync().result;
console.log("users");
users.map((user) =>
console.log(
user.user_name,
user.name,
user.email,
user.sys_domain_path,
user.name,
user.sys_id
)
);
dataStore.save(
User.tableModel,
users.map(
(user) =>
new User(
user.user_name,
user.name,
user.email,
user.sys_domain_path,
user.user_name,
user.sys_id
)
)
);
offset = offset + 100;
console.log(`offset: ${offset}`);
} while (offset < 300);
}
function fullSyncGroups({ client, dataStore }) {
let offset = 0;
do {
const response = client.fetchSync(
`/api/now/table/sys_user_group?sysparm_query=active%3Dtrue&sysparm_limit=100&sysparm_offset=${offset}`
);
if (!response.ok) {
console.log("Error status:", response.status, response.statusText);
console.log("Error body:", response.textSync());
throw new Error("Network response was not ok");
}
const groups = response.jsonSync().result;
groups.map((group) =>
console.log(
group.name,
group.name,
"/",
group.name,
group.sys_id,
group.parent.value
)
);
dataStore.save(
Group.tableModel,
groups.map(
(group) =>
new Group(
group.name,
group.name,
"/",
group.name,
group.sys_id,
group.parent.value
)
)
);
offset = offset + 100;
console.log(`offset: ${offset}`);
} while (offset < 400);
}
function fullSyncUserGroupMapping({ client, dataStore }) {
let offset = 0;
do {
const response = client.fetchSync(
`/api/now/table/sys_user_grmember?&sysparm_limit=100&sysparm_offset=${offset}`
);
if (!response.ok) {
console.log("Error status:", response.status, response.statusText);
console.log("Error body:", response.textSync());
throw new Error("Network response was not ok");
}
const mappings = response.jsonSync().result;
mappings.map((mapping) =>
console.log(mapping.user.value, mapping.group.value)
);
dataStore.save(
UserGroupMapping.tableModel,
mappings.map(
(mapping) =>
new UserGroupMapping(mapping.user.value, mapping.group.value)
)
);
offset = offset + 100;
console.log(`offset: ${offset}`);
} while (offset < 400);
}
integration.define({
synchronizations: [
{
name: "snowUserGroups", // Logical name
fullSyncFunction: fullSync,
},
],
model: {
tables: [User.tableModel, Group.tableModel, UserGroupMapping.tableModel],
},
});
<!--NeedCopy-->