Appearance
对接微软AD域同步组织架构和成员
概述
在企业内部通常会使用微软AD域
进行组织架构管理、用户管理、 下面是同步组织架构和成员到织信的步骤。
实现代码
javascript
const syncOrg = () => {
let connection = null;
try {
connection = informat.ldap.connect({
providerURL: 'LDAP://1.13.173.190:389',
securityPrincipal: 'userName',
securityCredentials: 'password',
});
// 查询ou=Group,dc=informat,dc=cn目录所有部门
const result = connect.search('ou=Group,dc=informat,dc=cn', 'objectClass=group', {
searchScope: 'SUBTREE', // 搜索的限定范围,默认为 SUBTREE。SUBTREE 返回所有满足条件的条目,ONELEVEL 返回同级的条目,OBJECT 只返回满足条件的对象
});
// 输出所有条目的名称及其属性
result.forEach(r => {
let id = null
let name = null
let description = null
let parentId = null
r.attributes.forEach(ra => {
if (ra.id === 'cn') {
id = ra.values[0]
}
if (ra.id === 'name') {
name = ra.values[0]
}
if (ra.id === 'description') {
description = ra.values[0]
}
if (ra.id === 'memberOf') {
const cnMatch = ra.values[0].match(/CN=([^,]+)/);
parentId = cnMatch ? cnMatch[1] : null;
}
});
let dept = {
id: id,
name: name,
description: description,
parentId: parentId
}
addDept(dept)
});
} catch (e) {
//连接ldap服务器或者认证失败
console.error('ldap login failure')
} finally {
if (connection != null) {
connection.close();
}
}
}
/**
* 添加部门
* @param dept
*/
const addDept = (dept) => {
let deptExist = informat.dept.getDept(dept.id);
if (deptExist) {
return;
}
informat.dept.addDept({
id:dept.id,
name:dept.name,
shortName:dept.name,
parentId: dept.parentId ? dept.parentId : 'root',
ownerList:['zhangsan'], // 部门属主,根据实际情况修改
remark: dept.description
});
}
javascript
const syncAccount = () => {
let connection = null;
try {
connection = informat.ldap.connect({
providerURL: 'LDAP://1.13.173.190:389',
securityPrincipal: 'userName',
securityCredentials: 'password',
});
// 查询cn=Users,dc=informat,dc=cn目录所有用户
const result = connect.search('cn=Users,dc=informat,dc=cn', 'objectClass=user', {
searchScope: 'SUBTREE', // 搜索的限定范围,默认为 SUBTREE。SUBTREE 返回所有满足条件的条目,ONELEVEL 返回同级的条目,OBJECT 只返回满足条件的对象
});
// 输出所有条目的名称及其属性
result.forEach(r => {
let userName = null
let name = null
let userAccountControl = null
let deptList = []
r.attributes.forEach(ra => {
if (ra.id === 'userPrincipalName') {
userName = ra.values[0]
}
if (ra.id === 'name') {
name = ra.values[0]
}
if (ra.id === 'userAccountControl') {
userAccountControl = ra.values[0]
}
if (ra.id === 'memberOf') {
deptList = ra.values.filter(group => group.includes('OU='))
.map(group => {
// 提取 CN
const cnMatch = group.match(/CN=([^,]+)/);
return cnMatch ? cnMatch[1] : null;
}).filter(cn => cn !== null);
}
});
// 生成织信账号对象
let account = {
userName: userName,
name: name,
password: 'informat1234', // 默认密码
deptList: deptList
}
if (isDisableAccount(userAccountControl)) {
// 该AD域账户如果为禁用状态则禁用织信账号
disableAccount(account)
}
addAccount(account)
});
} catch (e) {
//连接ldap服务器或者认证失败
console.error('ldap login failure');
} finally {
if (connection != null) {
connection.close();
}
}
}
const addAccount = (account) => {
// 创建系统账号
let accountList = informat.system.queryAccountList({
pageSize:-1,
filter: {
conditionList: [
{
fieldId: 'userName',
opt: 'eq',
value: account.userName
}
]
}
})
if (accountList.length !== 0) {
let existAccount = accountList[0];
if (!existAccount.isValid) {
informat.system.setAccountValid(existAccount.id, true);
}
return
}
let accountId = informat.system.addAccount({
name: account.name,
avatar: 'pic1.png',
userName: account.userName,
password: account.password
});
// 给账号添加部门和系统角色
informat.company.addCompanyMember(accountId, account.deptList, ['normal'])
}
/**
* 禁用账户
* @param account
*/
const disableAccount = (account) => {
// 查询已存在账户
let accountList = informat.system.queryAccountList({
pageSize:-1,
filter: {
conditionList: [
{
fieldId: 'userName',
opt: 'eq',
value: account.userName
}
]
}
})
if (accountList.length !== 0) {
let existAccount = accountList[0];
if (existAccount.isValid) {
informat.system.setAccountValid(existAccount.id, false);
}
}
}
/**
* 是否禁用
* @param userAccContr
* @returns {boolean}
*/
const isDisableAccount = (userAccContr) => {
// TRUSTED_TO_AUTH_FOR_DELEGATION - 允许该帐户进行委派
if (userAccContr >= 16777216) {
userAccContr = userAccContr - 16777216;
}
// PASSWORD_EXPIRED - (Windows 2000/Windows Server 2003) 用户的密码已过期
if (userAccContr >= 8388608) {
userAccContr = userAccContr - 8388608;
}
//DONT_REQ_PREAUTH
if (userAccContr >= 4194304) {
userAccContr = userAccContr - 4194304;
}
// USE_DES_KEY_ONLY - (Windows 2000/Windows Server 2003) 将此用户限制为仅使用数据加密标准 (DES) 加密类型的密钥
if (userAccContr >= 2097152) {
userAccContr = userAccContr - 2097152;
}
// NOT_DELEGATED - 设置此标志后,即使将服务帐户设置为信任其进行 Kerberos 委派,也不会将用户的安全上下文委派给该服务
if (userAccContr >= 1048576) {
userAccContr = userAccContr - 1048576;
}
// TRUSTED_FOR_DELEGATION - 设置此标志后,将信任运行服务的服务帐户(用户或计算机帐户)进行 Kerberos 委派。任何此类服务都可模拟请求该服务的客户端。若要允许服务进行 Kerberos 委派,必须在服务帐户的 userAccountControl 属性上设置此标志
if (userAccContr >= 524288) {
userAccContr = userAccContr - 524288;
}
// SMARTCARD_REQUIRED - 设置此标志后,将强制用户使用智能卡登录
if (userAccContr >= 262144) {
userAccContr = userAccContr - 262144;
}
// MNS_LOGON_ACCOUNT - 这是 MNS 登录帐户
if (userAccContr >= 131072) {
userAccContr = userAccContr - 131072;
}
// DONT_EXPIRE_PASSWORD-密码永不过期
if (userAccContr >= 65536) {
userAccContr = userAccContr - 65536;
}
// MNS_LOGON_ACCOUNT - 这是 MNS 登录帐户
if (userAccContr >= 2097152) {
userAccContr = userAccContr - 2097152;
}
// SERVER_TRUST_ACCOUNT - 这是属于该域的域控制器的计算机帐户
if (userAccContr >= 8192) {
userAccContr = userAccContr - 8192;
}
// WORKSTATION_TRUST_ACCOUNT - 这是运行 Microsoft Windows NT 4.0 Workstation、Microsoft Windows NT 4.0 Server、Microsoft Windows 2000 Professional 或 Windows 2000 Server 并且属于该域的计算机的计算机帐户
if (userAccContr >= 4096) {
userAccContr = userAccContr - 4096;
}
// INTERDOMAIN_TRUST_ACCOUNT - 对于信任其他域的系统域,此属性允许信任该系统域的帐户
if (userAccContr >= 2048) {
userAccContr = userAccContr - 2048;
}
//NORMAL_ACCOUNT - 这是表示典型用户的默认帐户类型
if (userAccContr >= 512) {
userAccContr = userAccContr - 512;
}
// TEMP_DUPLICATE_ACCOUNT - 此帐户属于其主帐户位于另一个域中的用户。此帐户为用户提供访问该域的权限,但不提供访问信任该域的任何域的权限。有时将这种帐户称为“本地用户帐户”
if (userAccContr >= 256) {
userAccContr = userAccContr - 256;
}
//ENCRYPTED_TEXT_PASSWORD_ALLOWED - 用户可以发送加密的密码
if (userAccContr >= 128) {
userAccContr = userAccContr - 128;
}
//PASSWD_CANT_CHANGE - 用户不能更改密码。可以读取此标志,但不能直接设置它
if (userAccContr >= 64) {
userAccContr = userAccContr - 64;
}
// PASSWD_NOTREQD - 不需要密码
if (userAccContr >= 32)
{
userAccContr = userAccContr - 32;
}
// LOCKOUT
if (userAccContr >= 16) {
userAccContr = userAccContr - 16;
}
// HOMEDIR_REQUIRED - 需要主文件夹
if (userAccContr >= 8) {
userAccContr = userAccContr - 8;
}
return userAccContr >= 2;
}