下游同步
统一身份管理系统会向应用推送账户数据,包括人员,组织,部门,行政区划以及组织结构和组织人员等。
当管理员在进行增加部门、增加人员、修改人员等账户管理操作时,会触发数据推送动作。
应用系统需要提供一个回调地址 URL,当统一身份管理系统推送账户数据时,会以 HTTP POST 方式调用该地址,将账户数据以 JSON 格式发送给应用。
同步流程
下游同步的主要工作包括以下步骤:
- 在统一身份管理系统中,为应用系统配置下游同步策略,获得应用标识,签名
token和加密aes-key. - 在统一身份管理系统中,当用户或部门数据发生变化时,向应用系统提供的订阅
URL推送数据更新消息。 - 在应用系统中,通过订阅
URL接收统一身份管理系统的用户或部门更新数据消息。 - 在应用系统中,对接收的用户或部门更新数据消息进行解密,并验证签名,保障数据的机密性,完整性和真实性。
- 在应用系统中,先对解密后的数据进行分析,如判断是用户还是部门数据,数据的操作是增加,修改,删除,重命名,移动等操作,然后,更新到应用系统。
应用配置
在统一身份管理系统中,需要为第三方应用配置下列信息:
- 应用名称:第三方应用名称。
- 应用标识:系统自动分配。
- 接口地址:用于接收推送的数据,由第三方应用提供。
- 加密 aes-key:数据加密密钥,由系统产生,可更换。
- 签名 token:数据签名密钥,由系统产生,可更换。
接口说明
URL 请求路径和方法
Path: [第三方应用接口]
Method: POST
HTTP 请求
请求体参数:
| 字段 | 属性 | 是否必须 | 描述 |
|---|---|---|---|
| signature | 数据签名 | 是 | |
| encrypt | 加密数据 | 是 | |
| timeStamp | 时间戳 | 是 | |
| nonce | 随机数 | 是 |
{
"timeStamp": 1663496762749,
"msg_signature": "851990827b8d5cfd36b984fa69c75721dd37c3fe",
"encrypt": "n2v2XLn5Zr4c0KtSZR6jxdhJtiAeyGnUgH0mQvI2EBTdLm0ztK02EgIIIjHKLLRxvlGArI3+BI4noSjx6AZZotYP75RhUSXjM3OvSkZUIJdmplT/rH0D3kBHNYNtjcd3PTMpyuWkctI1Mwj0ExwlXonltaVNnT09eKlh8Qg8GDEbR+m2IKZudglTu4O1qFeWU7cOF7xTPtFUKSVguF9Qvj5eg9j8l8gCoQy54fKNlZG4a+kQMJS7S9gKTi1pVCIyea0RjcjWnBJwrhpHGFgsS9ssKzIrwVZEJ0lbrbMkFTUxPEKvGIreJAlSZkTKsCOa5AcJ0NirahsWzmLUlXLriaYCHbCRFPaUpPuTdvS5BbXlRlqqAOyOZQxVw9XMKvHU",
"nonce": "sYnwp45K5LBTnlOj"
}解密数据示例:
{
"data": {
"id": "...",
"uid": "...",
"emailAddress": "...",
"cellphoneNumber": "...",
"cn": "...",
"displayName": "...",
"title": "...",
"hiredDate": "...",
"status": "..."
},
"operationType": "create",
"nodeType": "person"
}HTTP 响应
响应头(Header):
| 字段 | 值 | 是否必须 | 描述 |
|---|---|---|---|
| content-type | application/json;charset=UTF-8 | NO |
响应体(Body):
| 字段 | 类型 | 描述 |
|---|---|---|
| status | 状态码 | 0,成功;-1,失败。 |
| message | string | 返回“成功”,或失败的原因。 |
响应示例:
成功示例:
{
"status": 0,
"message": "成功"
}失败示例:
{
"status": -1,
"message": "解密数据失败。"
}{
"status": -1,
"message": "验证签名失败。"
}后端代码示例(Java):
public class SampleController {
public Map<String, String> callBack(
@RequestParam(value = "msg_signature", required = false) String msg_signature,
@RequestParam(value = "timestamp", required = false) String timeStamp,
@RequestParam(value = "nonce", required = false) String nonce,
@RequestBody(required = false) JSONObject json) {
try {
// 1. 从http请求中获取加解密参数
// 2. 使用加解密类型
// encodingAesKey 在统一身份管理系统中设置的加密 aes-Key
// token 在统一身份管理系统中设置的签名 token
// appId 在统一身份管理系统中显示的应用标识
SyncDataCrypto callbackCrypto = new SyncDataCrypto(encodingAesKey, token, appId);
String encryptMsg = json.getString("encrypt");
String decryptMsg = callbackCrypto.getDecryptMsg(msg_signature, timeStamp, nonce, encryptMsg);
// 3. 反序列化回调事件json数据
JSONObject eventJson = JSON.parseObject(decryptMsg);
String eventType = eventJson.getString("EventType");
// 4. 根据EventType分类处理
if ("check_url".equals(eventType)) {
// 测试回调url的正确性
bizLogger.info("测试回调url的正确性");
} else if ("user_add_org".equals(eventType)) {
// 处理通讯录用户增加事件
bizLogger.info("发生了:" + eventType + "事件");
} else {
// 添加其他已注册的
bizLogger.info("发生了:" + eventType + "事件");
}
// 5. 返回success的加密数据
return callbackCrypto.getEncryptedMap("success");
} catch (EncryptException e) {
e.printStackTrace();
}
return null;
}
}数据详解
应用回调接口收到的请求数据格式如下所示:
json{ "timeStamp": 1663496762749, "msg_signature": "851990827b8d5cfd36b984fa69c75721dd37c3fe", "encrypt": "n2v2XLn5Zr4c0KtSZR6jxdhJtiAeyGnUgH0mQvI2EBTdLm0ztK02EgIIIjHKLLRxvlGArI3+BI4noSjx6AZZotYP75RhUSXjM3OvSkZUIJdmplT/rH0D3kBHNYNtjcd3PTMpyuWkctI1Mwj0ExwlXonltaVNnT09eKlh8Qg8GDEbR+m2IKZudglTu4O1qFeWU7cOF7xTPtFUKSVguF9Qvj5eg9j8l8gCoQy54fKNlZG4a+kQMJS7S9gKTi1pVCIyea0RjcjWnBJwrhpHGFgsS9ssKzIrwVZEJ0lbrbMkFTUxPEKvGIreJAlSZkTKsCOa5AcJ0NirahsWzmLUlXLriaYCHbCRFPaUpPuTdvS5BbXlRlqqAOyOZQxVw9XMKvHU", "nonce": "sYnwp45K5LBTnlOj" }字段说明:
timeStamp: 时间戳msg_signature: 签名数据,用于验证发送者身份以及数据完整性encrypt: 密文数据,经过加密的业务数据,例如账户数据nonce: 随机数,增强交互安全性
解密后,得到的数据明文格式如下所示:
json{ "data": { "id": "...", "uid": "...", "emailAddress": "...", "cellphoneNumber": "...", "cn": "...", "displayName": "...", "title": "...", "hiredDate": "...", "status": "..." }, "extra": { }, "operationType": "create", "dataType": "person" }
操作类型
字段名:operationType
- create: 创建数据
- update: 修改数据
- delete: 删除数据
- join: 加入组织结构,例如: 为部门添加人员,为部门添加子部门等
- quit: 离开组织结构,例如: 从部门删除人员,从部门删除子部门等
- init: 初始化数据
- noop: 无操作
额外数据
字段名:extra
额外数据存储的是辅助信息,通常为 data 字段的上级部门,组织,行政区划等信息,或者人员所在的部门信息。 在同步类型为 join 和 quit 时,会使用到 extra 字段。
数据类型
字段名:dataType
- person: 人员
- organization: 组织
- unit: 部门
- administrative_division: 行政区划
- organization_unit: 组织结构
- organization_person: 组织人员
- organization_unit_all: 一整套组织结构
人员数据字段
- id: 标识
- uid: 用户名
- cn: 姓名
- displayName: 昵称
- title: 职位
- hiredDate: 入职日期
- identityNumber: 身份证号
- cellphoneNumber: 手机号
- emailAddress: 电子邮箱
- photo: 头像
- status: 状态
- ON_JOB: 在职
- OFF_JOB: 离职
- SUSPENSION: 停职
- RETIREMENT1: 退休
- RETIREMENT2: 离休
提示
从统一身份管理系统同步到应用的人员数据的属性,是根据下游同步策略配置的,可能并不是全部属性。
行政区划数据字段
- id: 标识
- name: 行政区划名称
- code: 行政区划代码
提示
从统一身份管理系统同步到应用的行政区划数据的属性,是根据下游同步策略配置的,可能并不是全部属性。
组织数据字段
- id: 标识
- name: 名称
- uscc: 统一社会信用代码
- lr: 法人
- lrCellphoneNumber: 法人联系方式
- registeredAddress: 注册地址
- administrativeDivision: 行政区划
- businessScope: 经营范围
- description: 描述
提示
从统一身份管理系统同步到应用的组织数据的属性,是根据下游同步策略配置的,可能并不是全部属性。
部门数据字段
- id: 标识
- name: 名称
- telephoneNumber: 电话号码
- businessCategory: 业务类别
- description: 描述
提示
从统一身份管理系统同步到应用的部门数据的属性,是根据下游同步策略配置的,可能并不是全部属性。
组织结构数据字段
ouId: 组织结构IDdisplayOrder: 顺序号,用于指定显示顺序ouRootId: 一级组织结构ID,即组织结构树的根IDtag: 标签, 用于区分同名的一级组织结构id: 行政区划/组织/部门的IDtype: 类型,参见数据类型dataTypeouParentId: 父级组织结构IDoperation: 操作类类型,参加 操作类型
组织人员数据字段
ouId: 组织结构IDpersonId: 人员IDid: 唯一标识
新增人员
{
"timeStamp":1701920579871,
"data":{
"uid":"lian",
"cellphoneNumber":"13888888888",
"emailAddress":"lian@topeid.com",
"displayName":"安安",
"hiredDate":"2007-10-14T16:00:00",
"cn":"李安","id":"1732606597445849088",
"title":"总经理",
"status":"ON_JOB"
},
"dataType":"person",
"operationType":"create"
}修改人员
{
"timeStamp":1701920838420,
"data":{
"uid":"lian",
"cellphoneNumber":"13666666666",
"emailAddress":"lian@topeid.com",
"displayName":"安安",
"hiredDate":"2007-10-14T16:00:00",
"cn":"李安",
"id":"1732606597445849088",
"title":"设计师",
"status":"ON_JOB"
},
"dataType":"person",
"operationType":"update"
}删除人员
{
"timeStamp":1701929260395,
"data":{
"uid":"lian",
"cellphoneNumber":"13666666666",
"emailAddress":"lian@topeid.com",
"displayName":"安安",
"hiredDate":"2007-10-14T16:00:00",
"cn":"李安",
"id":"1732606597445849088",
"title":"设计师",
"status":"ON_JOB"
},
"dataType":"person",
"operationType":"delete"
}新增行政区划
{
"timeStamp":1701930055345,
"data":{
"name":"河北省",
"id":"1728238244094558208"
},
"dataType":"administrative_division",
"operationType":"create"
}修改行政区划
{
"timeStamp":1701930121874,
"data":{
"code":"130000",
"name":"河北省",
"id":"1728238244094558208"
},
"dataType":"administrative_division",
"operationType":"update"
}删除行政区划
{
"timeStamp":1701930208214,
"data":{
"code":"370001",
"name":"山东省",
"id":"1728238244094558208"
},
"dataType":"administrative_division",
"operationType":"delete"
}新增组织
{
"timeStamp":1701931243978,
"data":{
"administrativeDivision":"",
"registeredAddress":"",
"lr":"",
"lrCellphoneNumber":"",
"name":"测试组织01",
"uscc":"123456789012345678",
"id":"1732651333951033344"
},
"dataType":"organization",
"operationType":"create"
}修改组织
{
"timeStamp":1701931390572,
"data":{
"administrativeDivision":"河北省石家庄市藁城区",
"registeredAddress":"河北省石家庄市藁城区新华路1号",
"lr":"李安",
"lrCellphoneNumber":"13888888888",
"name":"测试组织01",
"uscc":"123456789012345678",
"id":"1732651333951033344"
},
"dataType":"organization",
"operationType":"update"
}删除组织
{
"timeStamp":1701931390572,
"data":{
"administrativeDivision":"河北省石家庄市藁城区",
"registeredAddress":"河北省石家庄市藁城区新华路1号",
"lr":"李安",
"lrCellphoneNumber":"13888888888",
"name":"测试组织01",
"uscc":"123456789012345678",
"id":"1732651333951033344"
},
"dataType":"organization",
"operationType":"delete"
}新增部门
{
"timeStamp":1701931697652,
"data":{
"name":"测试部门01",
"code":"001",
"description":"",
"id":"1732653227104669696"
},
"dataType":"unit",
"operationType":"create"
}修改部门
{
"timeStamp":1701931757811,
"data":{
"name":"测试部门01",
"code":"001",
"description":"这是一个测试部门。",
"id":"1732653227104669696"
},
"dataType":"unit",
"operationType":"update"
}删除部门
{
"timeStamp":1711202513752,
"data":{
"name":"测试部门01",
"code":"001",
"id":"1732653227104669696"
},
"dataType":"unit",
"operationType":"delete"
}添加组织人员
{
"timeStamp":1701933800540,
"data":{
"uid":"lian",
"cellphoneNumber":"13666666666",
"emailAddress":"lian@topeid.com",
"displayName":"安安",
"hiredDate":"2007-10-14T16:00:00",
"cn":"李安",
"id":"1732606597445849088",
"title":"设计师",
"status":"ON_JOB"
},
"dataType":"organization_person",
"extra":{
"ouId":"1732661996316397568",
"ouRootId":"1732656494157107200",
"id":"1732651333951033344",
"type":"organization",
"ouParentId":"1732661339907821568"
},
"operationType":"join"
}字段说明:
data: 主要数据,参见人员数据字段extra: 辅助数据ouId: 组织结构ID,即人员所在组织结构ouParentID: 父级组织结构IDouRootId: 一级组织结构ID,即组织结构树的根IDid: 行政区划/组织/部门的IDtype: 类型,参考数据类型dataType
dataType: 数据类型,参考数据类型dataTypeoperationType: 操作类型
删除组织人员
{
"timeStamp":1701934214419,
"data":{
"uid":"lian",
"cellphoneNumber":"13666666666",
"emailAddress":"lian@topeid.com",
"displayName":"安安",
"hiredDate":"2007-10-14T16:00:00",
"cn":"李安",
"id":"1732606597445849088",
"title":"设计师",
"status":"ON_JOB"
},
"dataType":"organization_person",
"extra":{
"ouId":"1732661996316397568",
"ouRootId":"1732656494157107200",
"id":"1732651333951033344",
"type":"organization",
"ouParentId":"1732661339907821568"
},
"operationType":"quit"
}创建组织结构单位
把行政区划,组织和部门加入到组织结构。
创建一级组织结构单位
应用不会收到创建一级组织结构单位的推送数据,因为在创建之前无法在应用同步策略中配置。
创建二级组织结构单位
{
"timeStamp":1716022399886,
"data":{
"ouId":"1791753926295556096",
"displayOrder":"100",
"ouRootId":"1791713310392061952",
"tag":"",
"id":"1767763037495889920",
"type":"administrative_division",
"ouParentId":"1791713310392061952"},
"dataType":"organization_unit",
"extra":{
"ouId":"1791713310392061952",
"displayOrder":"10",
"ouRootId":"1791713310392061952",
"tag":"测试应用01",
"id":"1767763020282466304",
"type":"administrative_division"
},
"origin":{
"code":"130900",
"name":"沧州市",
"id":"1767763037495889920"
},
"operationType":"join"
}创建三级组织结构单位
{
"timeStamp":1716022412888,
"data":{
"ouId":"1791753980813119488",
"displayOrder":"10",
"ouRootId":"1791713310392061952",
"tag":"",
"id":"1767763037592358912",
"type":"administrative_division",
"ouParentId":"1791713367489122304"
},
"dataType":"organization_unit",
"extra":{
"ouId":"1791713367489122304",
"displayOrder":"10",
"ouRootId":"1791713310392061952",
"tag":"",
"id":"1767763037495889920",
"type":"administrative_division",
"ouParentId":"1791713310392061952"
},
"origin":{
"code":"130902",
"name":"新华区",
"id":"1767763037592358912"
},
"operationType":"join"
}字段说明:
data: 主要数据ouId: 组织结构IDouParentID: 父级组织结构IDouRootId: 一级组织结构ID,即组织结构树的根IDid: 行政区划/组织/部门的IDtype: 数据类型,参见 数据类型tag: 标签, 用于区分同名的同级组织结构单位displayOrder: 顺序号,用于指定显示顺序
extra: 辅助数据ouId: 组织结构ID,与data.ouParentID相等ouParentID: 父级组织结构IDouRootId: 一级组织结构ID,即组织结构树的根IDid: 行政区划/组织/部门的IDtype: 类型,参见数据类型dataTypetag: 标签, 用于区分同名的同级组织结构单位displayOrder: 顺序号,用于指定显示顺序
origin: 所添加组织结构的基础数据,示例为行政区划数据name: 行政区划名称code: 行政区划代码id: 行政区划ID
dataType: 数据类型,参见 数据类型operationType: 操作类型,参加 操作类型
提示
如果 extra.ouParentID 不存在或者为空,表明正在添加的是二级组织结构单位。
此时,需要判断应用系统本地是否已经创建了一级组织结构单位。如果一级组织结构单位不存在,需要先根据 extra 中的信息创建一级组织结构单位,再添加二级组织结构单位。
修改组织结构单位
目前只支持修改一级组织结构的标签和顺序号。
{
"timeStamp":1711206432429,
"data":{
"ouId":"1771527916161732608",
"displayOrder":"100",
"ouRootId":"1771527916161732608",
"tag":"测试标签01",
"id":"1766705245548843008",
"type":"organization"
},
"dataType":"organization_unit",
"operationType":"update"
}删除组织结构单位
应用系统接收到的数据只包含被删除的组织结构单位的信息,不包含其下属的子级单位和人员信息。
应用系统自行处理与被删除组织结构单位相关联的信息,包括该单位所属的人员信息,该单位下属的(多级)单位和人员信息,应用系统中与该单位关联的其他信息,等等。
删除一级组织结构单位
如果 ouId 与 ouRootId 相同,表示删除的是一级组织结构单位。
{
"timeStamp":1716027626710,
"data":{
"ouId":"1791772531473125376",
"displayOrder":"10",
"ouRootId":"1791772531473125376",
"tag":"测试应用01",
"id":"1767763020282466304"
"type":"administrative_division"
},
"dataType":"organization_unit",
"origin":{
"code":"130000",
"name":"河北省",
"id":"1767763020282466304"
},
"operationType":"quit"
}删除非一级组织结构单位
如果删除的是非一级组织结构单位,那么 extra 中包含其上一级组织结构单位的信息。
删除二级组织结构单位
{
"timeStamp":1716027009973,
"data":{
"ouId":"1791772612523855872",
"displayOrder":"10",
"ouRootId":"1791772531473125376",
"tag":"",
"id":"1767763037495889920",
"type":"administrative_division",
"ouParentId":"1791772531473125376"
},
"dataType":"organization_unit",
"extra":{
"ouId":"1791772531473125376",
"displayOrder":"10",
"ouRootId":"1791772531473125376",
"tag":"测试应用01",
"id":"1767763020282466304",
"type":"administrative_division"
},
"origin":{
"code":"130900",
"name":"沧州市",
"id":"1767763037495889920"
},
"operationType":"quit"
}删除三级组织结构单位
{
"timeStamp":1716026979952,
"data":{
"ouId":"1791772666882035712",
"displayOrder":"10",
"ouRootId":"1791772531473125376",
"tag":"",
"id":"1767763037592358912",
"type":"administrative_division",
"ouParentId":"1791772612523855872"
},
"dataType":"organization_unit",
"extra":{
"ouId":"1791772612523855872",
"displayOrder":"10",
"ouRootId":"1791772531473125376",
"tag":"",
"id":"1767763037495889920",
"type":"administrative_division",
"ouParentId":"1791772531473125376"
},
"origin":{
"code":"130902",
"name":"新华区",
"id":"1767763037592358912"
},
"operationType":"quit"
}批量同步
批量同步是一次同步多条主数据,如一套组织结构数据。
新增组织结构
同步一套新增的、完整的组织结构数据及其相关的基础数据。例如,手动同步或初始化是常见的场景。
{
"data":{
"organization-people":[
{"ouId":"1791714245570859008","personId":"1781328130930249728","id":"1791714313396948992"}
],
"organizations":[
{"administrativeDivision":"130902","registeredAddress":"河北省沧州市新华区黄河东路","lr":"贾先生","lrCellphoneNumber":"13800138000","name":"沧州某某粮食储备有限公司","uscc":"9113xxx110xxx02xxx","id":"1772170700451352576"}
],
"units":[{"name":"业务部","id":"1742821448562642944"}],
"people":[
{"uid":"liyi","emailAddress":"","id":"1781328130930249728","cn":"李一"}
],
"divisions":[
{"code":"130000","name":"河北省","id":"1767763020282466304"},
{"code":"130900","name":"沧州市","id":"1767763037495889920"},
{"code":"130902","name":"新华区","id":"1767763037592358912"}
],
"organization-units":[
{"ouId":"1791713310392061952","displayOrder":"1","ouRootId":"1791713310392061952","tag":"测试应用01","id":"1767763020282466304","type":"administrative_division"},
{"ouId":"1791713367489122304","displayOrder":"10","ouRootId":"1791713310392061952","tag":"","id":"1767763037495889920","type":"administrative_division","ouParentId":"1791713310392061952"},
{"ouId":"1791713434820284416","displayOrder":"10","ouRootId":"1791713310392061952","tag":"","id":"1767763037592358912","type":"administrative_division","ouParentId":"1791713367489122304"},
{"ouId":"1791714198129086464","displayOrder":"10","ouRootId":"1791713310392061952","tag":"","id":"1772170700451352576","type":"organization","ouParentId":"1791713434820284416"},
{"ouId":"1791714245570859008","displayOrder":"10","ouRootId":"1791713310392061952","tag":"","id":"1742821448562642944","type":"unit","ouParentId":"1791714198129086464"}
]
},
"dataType":"organization_unit_all",
"operationType":"init",
"timeStamp":1716013001769
}字段说明:
修改组织结构
对一套组织结构中的多条单位和人员信息进行修改。
{
"operationType": "update",
"dataType": "organization_unit_all",
"timeStamp": 1724050531589,
"data": {
"divisions": [
{
"id": "1767763020282466304",
"name": "河北省",
"code": "130000"
},
{
"id": "1767763020416684032",
"name": "石家庄市",
"code": "130100"
},
{
"id": "1767763037495889920",
"name": "沧州市",
"code": "130900"
}
],
"organizations": [
{
"id": "1772170700451352576",
"name": "沧州国粮粮食储备有限公司",
"uscc": "911309011095402112",
"lr": "贾金海",
"lrCellphoneNumber": "15803175128",
"registeredAddress": "河北省沧州市新华区黄河东路9号",
"administrativeDivision": "130902"
}
],
"units": [
{
"id": "1742821448562642944",
"name": "业务部"
}
],
"people": [
{
"id": "1781328130930249728",
"uid": "liyi",
"cn": "李一",
"emailAddress": "liyi@topeid.com",
"identityNumber": "130801198911043059",
"cellphoneNumber": "18614019377"
}
],
"organization-units": [
{
"displayOrder": "0",
"tag": "测试应用01",
"ouId": "1791713310392061952",
"ouRootId": "1791713310392061952",
"id": "1767763020282466304",
"type": "administrative_division",
"operation": "noop"
},
{
"displayOrder": "100",
"tag": "",
"ouId": "1791753392083832832",
"ouParentId": "1791713310392061952",
"ouRootId": "1791713310392061952",
"id": "1767763020416684032",
"type": "administrative_division",
"operation": "update"
},
{
"displayOrder": "900",
"ouId": "1825426350014599168",
"ouParentId": "1791713310392061952",
"ouRootId": "1791713310392061952",
"id": "1767763037495889920",
"type": "administrative_division",
"operation": "create"
}
],
"organization-people": [
{
"id": "1825426350140428288",
"ouId": "1825426350014599168",
"personId": "1781328130930249728"
}
]
}
}字段说明:
