LDAP做為企業應用登錄認證服務開發點滴


【背景】

在互聯網大環境下,企業辦公應用近兩年呈現出蓬勃發展的態勢,這些應用必須兼容企業已有的登錄認證系統,LDAP(Lightweight Directory Access Protocol)做為標准的目錄服務,廣泛被企業使用。本文記錄接入到LDAP服務所遇到的問題以及解決辦法,希望對剛接觸LDAP的初學者有所幫助。

 

【環境、語音和開源庫】

linux

c++

OpenLDAP

 

【編譯】

從官網ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-2.4.44.tgz下載OpenLDAP最新版本

1、解壓縮OpenLDAP

定位到openldap-2.4.44.tgz所在目錄,執行tar zxvf  openldap-2.4.44.tgz解壓縮,在當前目錄下生成openldap-2.4.44目錄,ll命令查看包含的子目錄和文件:

2、vi命令查看INSTALL文件,初步了解編譯安裝步驟

3、編譯配置,執行如下命令:

./configure --prefix=/data/allanchen/opensource/openldap/openldap-2.4.44/build_lib --enable-backends=no --enable-slapd=no --enable-shared=no --with-pic=yes --with-cyrus-sasl=no
--prefix:設置編譯生成路徑
--enable-backends=no --enable-slapd=no,由於本次項目只是做為客戶端,取消服務端相關配置
當看到最后提示為“Please run "make depend" to build dependencies”時,configure執行成功
4、執行make depend,生成依賴項
5、執行make
6、執行make install,最終編譯完成,保護include頭文件以及lib靜態庫文件:
 
【用戶登錄認證】
由ldap_simple_bind_s(ld, dn, pw)函數完成用戶登錄認證,dn(distinguishedName)為認證用戶 完整路徑,pw為認證用戶密碼,dn由於對完整路徑的要求,使得我們很難配置基礎的base dn並由它來拼接用戶完整dn,所以,在認證登錄前,需設法查詢到用戶完整dn,ldap_search_s正好提供了相應功能,用戶設置base dn,並設置filter(可設置為(&(classobject=user)(sAMAccountName=loginName))),據此查找到用戶dn,從而調用ldap_simple_bind_s完成用戶登錄認證。
#include “ldap.h”
using namespace std;

LDAP * ld;
if ((ld = ldap_init(host.c_str(), LDAP_PORT)) == NULL) {
      cout << "ldap init failed" << endl;
      return 1;
}

int version = LDAP_VERSION3;
if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_SUCCESS) {
    cout << "set protocol version failed" << endl;
    return 1;
}

int max_timeout = 10;
if (ldap_set_option(ld, LDAP_OPT_TIMELIMIT,
    (void *)&max_timeout) != LDAP_SUCCESS) {
    cout << "set time limit failed" << endl;
    return 1;
}

// must do set
if (ldap_set_option(ld,LDAP_OPT_REFERRALS,LDAP_OPT_OFF) != LDAP_SUCCESS) {
    cout << "set referrals off failed" << endl;
    return 1;
}

// dn,pw管理員賬戶和密碼
int ret = LDAP_SUCCESS;
if ((ret = ldap_simple_bind_s(ld, dn_admin, pw_admin)) != LDAP_SUCCESS) {
    cout << "ldap_simple_bind_s failed" << endl;
    cout << "errcode : " << ret << endl;
    cout << "errmsg : " << ldap_err2string(ret) << endl;
    return 1;
}

LDAPMessage *result, *msg;
char * attrs[1];
attrs[0] = "distinguishedName";
char * filter = "(&(objectclass=user)(sAMAccountName=loginName))";
char * base = "DC=MyCompany,DC=com";
if ((ret = ldap_search_s(ld, base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result)) != LDAP_SUCCESS) {
    cout << "ldap_search_s failed" << endl;
    cout << "errcode :" << ret << endl;
    cout << "errmsg : " << ldap_err2string(ret) << endl;
    return 1;
}

char **vals;
if ((msg = ldap_first_entry(ld, result)) != NULL) {
    if ((vals = ldap_get_values(ld, msg, "distinguishedName")) != NULL) {
        char * dn = ldap_get_dn(ld, msg);
        ret = ldap_simple_bind_s(ld, dn, pw)
        if (ret == LDAP_SUCCESS) {
            cout << "auth succ";
        }
        else {
            cout << "auth failed";
        }
}
 
【結論】
重點在於要兼容不同企業LDAP用戶dn不同,以及同一企業不同不用不同層級dn。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM