LDAP是轻量目录访问协议(LightweightDirectory Access Protocol)的缩写,LDAP标准实际上是在X.500标准基础上产生的一个简化版本。
AD是Active Directory的缩写,AD是LDAP的一个应用实例,而不应该是LDAP本身。比如:windows域控的用户、权限管理应该是微软公司使用LDAP存储了一些数据来解决域控这个具体问题,只是AD顺便还提供了用户接口,也可以利用ActiveDirectory当做LDAP服务器存放一些自己的东西而已。
需求描述:SAP中的HR数据,比如用户姓名,手机号,邮箱地址,员工照片等,创建或者修改后需要同步更新到AD域服务器,用户登录windows操作系统后可以查看是否更新成功。
通信连接配置
LDAP前期配置需BASIS事先做好,执行LDAP事务码可以正常登录到AD目录。
连接器LDAP_HRO_500是一个RFC目标,通过SM59创建。详细的配置参数如下:
通过点击系统用户可以设置登录的用户:
LDAP账号密码需要设置:
LDAP连接器:
LDAP服务器:
通过查找功能可以查看AD库里的数据:
维护查询条件,注意格式:
执行LDAPMAP事务码,进行字段匹配。
· 1 筛选,用于查找SAP中的唯一数据
· 2 导入映射,设置筛选字段时需要设置此字段,用户查找AD域中的数据
· 3 导入映射,用于设置是否写入AD域字段
· 4 创建数据库,在SAP端生成新数据
· 5 创建LDAP,在AD端生成新数据
· 6 RDN,相对识别名称映射,本次传输的数据未使用到,但是系统程序里会校验这个字段,没有打勾的话会报错,此处只是有字段匹配被勾选,但是程序里未传输此字段的值
USERNAME– BAPIBNAME是必输项,但是本次场景中AD没有与其匹配的字段,所以将AD库中的主键值字段mail在此处匹配,程序里赋值的时候将邮箱地址赋值给BAPIBNAME。
执行数据传输
此次场景HR数据传输是定制化的字段,可以通过自开发程序来发送数据。通过SE19人员主数据的增强HRPAD00INFTY来将有变动的人员号写入自定义表,然后通过执行自开发程序发起数据同步。
自定义表ZHRLDAP_PERNR,与系统表HRLDAP_PERNR结构一样。
SE19中增强代码将需要同步的人员ID信息更新到上面的自定义表中。新建报表程序,取上表中人员数据发送到AD域。
*&---------------------------------------------------------------------*
*& Report Z01HRI0026
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT z01hri0026.
*----------------------------------------------------------------------
* type
*----------------------------------------------------------------------
TYPES: BEGIN OF ts_ldap_attr_l,
pernr LIKE lda_attr_l-pernr,
attr_tab LIKE lda_attr_l-attr_tab,
attr_field LIKE lda_attr_l-attr_field,
value LIKE lda_attr_l-value,
END OF ts_ldap_attr_l.
*----------------------------------------------------------------------
* table
*----------------------------------------------------------------------
DATA: gt_ldap TYPE TABLE OF Zhrldap_pernr,
gt_0001 TYPE TABLE OF pa0001,
gt_0105 TYPE TABLE OF pa0105.
*----------------------------------------------------------------------
* work area
*----------------------------------------------------------------------
DATA: gw_ldap TYPE Zhrldap_pernr,
gw_0001 TYPE pa0001,
gw_0105 TYPE pa0105.
*----------------------------------------------------------------------
* data
*----------------------------------------------------------------------
DATA: gv_error TYPE c.
*----------------------------------------------------------------------
* screen
*----------------------------------------------------------------------
SELECT-OPTIONS: s_date FOR sy-datum.
PARAMETERS: p_del TYPE c AS CHECKBOX.
*----------------------------------------------------------------------
* START-OF-SELECTION
*----------------------------------------------------------------------
START-OF-SELECTION.
IF p_del IS INITIAL.
* 取需要同步的数据
PERFORM frm_data_get.
* 编辑并同步数据
PERFORM frm_data_send.
ELSE.
DELETE FROM Zhrldap_pernr WHERE AEDTM in s_date and PROCESSED = 'X'.
ENDIF.
*&---------------------------------------------------------------------*
*& Form FRM_DATA_GET
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM frm_data_get .
SELECT *
FROM Zhrldap_pernr
INTO TABLE gt_ldap
WHERE processed = ''
AND aedtm in s_date.
CHECK gt_ldap IS NOT INITIAL.
SELECT pernr bukrs orgeh plans zzbz
FROM pa0001
INTO CORRESPONDING FIELDS OF TABLE gt_0001
FOR ALL ENTRIES IN gt_ldap
WHERE pernr = gt_ldap-pernr
AND begda <= sy-datum
AND endda >= sy-datum.
SELECT *
FROM pa0105
INTO CORRESPONDING FIELDS OF TABLE gt_0105
FOR ALL ENTRIES IN gt_ldap
WHERE pernr = gt_ldap-pernr
AND begda <= sy-datum
AND endda >= sy-datum.
SORT gt_0105 BY subty begda DESCENDING.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DATA_SEND
*&---------------------------------------------------------------------*
*& 编辑并同步数据
*&---------------------------------------------------------------------*
FORM frm_data_send .
DATA: attributes TYPE ts_ldap_attr_l OCCURS 0,
attributes_wa TYPE ts_ldap_attr_l,
lv_time TYPE i,
lv_deptn TYPE string,
lv_photo TYPE string,
lv_objid TYPE hrp1001-objid,
logsys LIKE tbdls-logsys,
ldapsrv LIKE lda_types-ldapserver,
errors LIKE bapiret2 OCCURS 0,
errors_wa LIKE bapiret2.
DATA: mid TYPE sy-msgid VALUE 'LDAPSYNC',
mtype TYPE sy-msgty VALUE 'I',
num TYPE sy-msgno.
LOOP AT gt_ldap INTO gw_ldap.
attributes_wa-pernr = gw_ldap-pernr.
* attributes_wa-attr_tab = 'EMPLOYEE'.
* attributes_wa-attr_field = 'KEY'.
** attributes_wa-value = gw_0105-usrid.
* APPEND attributes_wa TO attributes.
"邮件、手机号、SAP账号
CLEAR gw_0105.
READ TABLE gt_0105 INTO gw_0105 WITH KEY pernr = gw_ldap-pernr subty = '0006'.
IF gw_0105-usrid IS NOT INITIAL.
attributes_wa-attr_tab = 'USERNAME'.
attributes_wa-attr_field = 'BAPIBNAME'.
attributes_wa-value = gw_0105-usrid.
APPEND attributes_wa TO attributes.
else.
CONTINUE.
ENDIF.
CLEAR gw_0105.
READ TABLE gt_0105 INTO gw_0105 WITH KEY pernr = gw_ldap-pernr subty = '0004'.
IF gw_0105-usrid IS NOT INITIAL.
attributes_wa-attr_tab = 'EMPLOYEE'.
attributes_wa-attr_field = 'MOBILE'.
attributes_wa-value = gw_0105-usrid.
APPEND attributes_wa TO attributes.
ENDIF.
CLEAR gw_0105.
READ TABLE gt_0105 INTO gw_0105 WITH KEY pernr = gw_ldap-pernr subty = '0001'.
IF gw_0105-usrid IS NOT INITIAL.
attributes_wa-attr_tab = 'EMPLOYEE'.
attributes_wa-attr_field = 'BNAME'.
attributes_wa-value = gw_0105-usrid.
APPEND attributes_wa TO attributes.
ENDIF.
"同步公司、组织单位、职位
CLEAR gw_0001.
READ TABLE gt_0001 INTO gw_0001 WITH KEY pernr = gw_ldap-pernr.
attributes_wa-attr_tab = 'EMPLOYEE'.
attributes_wa-attr_field = 'PERNR'.
attributes_wa-value = gw_0001-pernr.
APPEND attributes_wa TO attributes.
"公司
SELECT SINGLE butxt
FROM t001
INTO @DATA(lv_butxt)
WHERE bukrs = @gw_0001-bukrs.
attributes_wa-attr_tab = 'EMPLOYEE'.
attributes_wa-attr_field = 'COMPANY'.
attributes_wa-value = lv_butxt.
APPEND attributes_wa TO attributes.
CLEAR lv_butxt.
"职务
if gw_0001-zzbz is INITIAL.
SELECT SINGLE stext
FROM hrp1000
INTO @DATA(lv_stext)
WHERE plvar = '01'
AND otype = 'S'
AND objid = @gw_0001-plans
AND istat = '1'
AND begda <= @sy-datum
AND endda >= @sy-datum
AND langu = '1'.
else.
lv_stext = gw_0001-zzbz.
endif.
attributes_wa-attr_tab = 'EMPLOYEE'.
attributes_wa-attr_field = 'TITLE'.
attributes_wa-value = lv_stext.
APPEND attributes_wa TO attributes.
CLEAR lv_stext.
"部门
lv_objid = gw_0001-orgeh.
"先检查当前条,不符合条件则检索上一级的组织
CLEAR: lv_time,lv_deptn.
IF lv_objid IS NOT INITIAL.
DO 10 TIMES.
lv_time = lv_time + 1.
SELECT SINGLE *
FROM hrp9503
INTO @DATA(lw_9503)
WHERE otype = 'O'
AND objid = @lv_objid
AND begda <= @sy-datum
AND endda >= @sy-datum.
IF sy-subrc = 0. "取到组织单位
SELECT SINGLE *
FROM hrp1000
INTO @DATA(lw_1000)
WHERE otype = 'O'
AND objid = @lv_objid
AND begda <= @sy-datum
AND endda >= @sy-datum.
IF lw_9503-zznsjgcj = '2'.
lv_deptn = lw_1000-mc_stext.
ELSEIF lw_9503-zznsjgcj = '1'.
IF lv_deptn IS INITIAL.
lv_deptn = lw_1000-mc_stext.
ELSE.
CONCATENATE lw_1000-mc_stext lv_deptn INTO lv_deptn.
ENDIF.
EXIT.
ENDIF.
ENDIF.
"检索上一级组织
SELECT SINGLE *
FROM hrp1001
INTO @DATA(lw_1001)
WHERE otype = 'O'
AND objid = @lv_objid
AND rsign = 'A'
AND relat = '002'
AND begda <= @sy-datum
AND endda >= @sy-datum.
IF sy-subrc = 0.
lv_objid = lw_1001-sobid.
ENDIF.
CLEAR: lw_9503,lw_1000,lw_1001.
ENDDO.
ENDIF.
attributes_wa-attr_tab = 'EMPLOYEE'.
attributes_wa-attr_field = 'DEPARTMENT'.
attributes_wa-value = lv_deptn.
APPEND attributes_wa TO attributes.
CLEAR lv_deptn.
* 取员工照片
PERFORM frm_get_photo USING gw_ldap-pernr CHANGING lv_photo.
attributes_wa-attr_tab = 'EMPLOYEE'.
attributes_wa-attr_field = 'PHOTO'.
attributes_wa-value = lv_photo.
APPEND attributes_wa TO attributes.
CLEAR lv_photo.
ENDLOOP.
* send attributes to ldap client
logsys = 'LDAP_HRQ_500'.
ldapsrv = 'AD_SINOCHEM'.
* send attributes
CALL FUNCTION 'SPLDAP_RECEIVE_ATTRIBUTES'
EXPORTING
logsys = logsys
serverid = ldapsrv
* ATTRIBUTES_S = attributes[]
* initial_run = ldapinitialrun
attributes_l = attributes[]
* ATTRIBUTES_X = TOTAL_ATTRS_X[].
IMPORTING
return = errors[].
IF NOT errors[] IS INITIAL.
READ TABLE errors INDEX 1 INTO errors_wa.
MESSAGE ID errors_wa-id TYPE errors_wa-type
NUMBER errors_wa-number
WITH errors_wa-message_v1 errors_wa-message_v2
errors_wa-message_v3 errors_wa-message_v4.
else.
MESSAGE ID mid TYPE mtype
NUMBER 022.
gw_ldap-PROCESSED = 'X'.
modify gt_ldap FROM gw_ldap TRANSPORTING PROCESSED WHERE PROCESSED = ''.
modify Zhrldap_pernr FROM TABLE gt_ldap.
commit WORK.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_GET_PHOTO
*&---------------------------------------------------------------------*
*& 取员工照片
*&---------------------------------------------------------------------*
*& --> LS_PA_REQUEST_PERNR
*& <-- LS_PA_REQUEST_PHOTO
*&---------------------------------------------------------------------*
FORM frm_get_photo USING pv_pernr
CHANGING pv_photo.
DATA: ls_image_info TYPE toav0,
lv_image_exists(1) TYPE c,
lv_len TYPE i,
lv_pos TYPE i,
lv_time TYPE i,
lt_mime TYPE TABLE OF W3MIME,
lv_content TYPE XSTRING,
lv_pernr TYPE p0001-pernr,
lt_data LIKE TABLE OF tbl1024,
lw_data like tbl1024.
* 以下用于取照片
CLEAR: ls_image_info,
lv_len,
lt_data,
lv_image_exists.
lv_pernr = pv_pernr."'20600010'.
"2、员工照片
CALL FUNCTION 'HR_IMAGE_EXISTS'
EXPORTING
p_pernr = lv_pernr
p_tclas = 'A'
p_begda = sy-datum
p_endda = sy-datum
IMPORTING
p_exists = lv_image_exists
p_connect_info = ls_image_info
EXCEPTIONS
error_connectiontable = 1
OTHERS = 2.
IF sy-subrc = 0.
CALL FUNCTION 'SCMS_AO_TABLE_GET'
EXPORTING
arc_id = ls_image_info-archiv_id
doc_id = ls_image_info-arc_doc_id
IMPORTING
length = lv_len
TABLES
data = lt_data
EXCEPTIONS
error_http = 1
error_archiv = 2
error_kernel = 3
error_config = 4
OTHERS = 5.
IF sy-subrc = 0.
LOOP AT lt_data INTO lw_data..
pv_photo = pv_photo && lw_data-LINE.
ENDLOOP.
exit.
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
input_length = lv_len
IMPORTING
buffer = lv_content
TABLES
binary_tab = lt_data
EXCEPTIONS
failed = 1
OTHERS = 2.
pv_photo = lv_content.
* CALL FUNCTION 'RSFO_XSTRING_TO_MIME'
* EXPORTING
* C_XSTRING = lv_content
* I_LENGTH = lv_len
* TABLES
* C_T_MIME = lt_MIME.
ENDIF.
ELSE.
* CLEAR GV_GLAG.
* GV_GLAG = 'X'.
* EXIT.
ENDIF.
ENDFORM.