使用oracle DBMS_LDAP验证针对Microsoft Active Directory的用户凭据

时间:2014-08-21 08:52:10

标签: oracle oracle10g ldap

我们正在尝试使用针对Microsoft AD的dbms_ldap对我们的应用程序用户进行身份验证,我们无法在离岸环境中对其进行测试

我们有三个具体问题

1)如何验证用户是否存在于Microsoft Active Directory

我们使用以下代码获取Application用户的专有名称

DBMS_LDAP.USE_EXCEPTION := FALSE;
retval := DBMS_LDAP.search_s(ld       => ldapSession,
                           base     => LDAP_BASE,
                           scope    => DBMS_LDAP.SCOPE_SUBTREE,
                           filter   => '(&(objectclass=USER)(SAMAccountName=' ||
                                       p_username || '))',
                           attrs    => attrList,
                           attronly => 0,
                           res      => ldapMessage);
  -- get the DN
if retval <> DBMS_LDAP_UTL.SUCCESS THEN
RAISE l_ldap_exception;
END IF;
userDN := DBMS_LDAP.get_dn(ldapSession, ldapMessage);

所以第一个问题是什么是

的价值
 userDN and ldapMessage

如果用户不存在于Microsoft AD

2)假设用户存在且输入了错误的密码,那将是retval的返回值

if p_password is null then
raise_application_error(-20000, 'Invalid Null password');
else
retval := DBMS_LDAP.simple_bind_s(ldapSession,userDN, p_password);
end if;

if retval <> DBMS_LDAP_UTL.SUCCESS THEN
RAISE l_ldap_exception;
and if;

3)我的第三个问题是假设用户已登录系统并且ldapsession仍然没有解除绑定识别重复会话的方法

3 个答案:

答案 0 :(得分:5)

警告警告警告

这不是一个答案,而是对使用以下代码验证用户的任何人的警告。

  retval := DBMS_LDAP.simple_bind_s(ldapSession, userDN, p_password);

按照设计(LDAP设计),如果密码为 null ,此函数调用将始终返回成功。这样做是为了允许匿名LDAP查询。这可能会在您的特定服务器上禁用,但并非总是如此。

因此,如果您想使用此函数,请确保使用if块将其包装,以确保用户提供的密码不为空。 e.g。

  if p_password is null then
    raise_application_error(-20000, 'Invalid Null password');
  else
    retval := DBMS_LDAP.simple_bind_s(ldapSession,userDN, p_password);
  end if;

有关详细信息,请参阅:http://www.inside-oracle-apex.com/dbms_ldapsimple_bind_s-apex_ldapauthenticate-and-null-password/

答案 1 :(得分:3)

首先,阅读文档。它几乎包含您回答问题所需的一切:http://docs.oracle.com/cd/E23943_01/oid.1111/e10186/dbmsldap_ref.htm

1)将引发NULL或get_dn_exception,我不确定。无论如何,另一种检查方法是计算搜索结果,你只需要检查计数是否> 0:

DBMS_LDAP.count_entries(ld => ldapSession, msg => ldapMessage)

2)retval只能是DMBS_LDAP.SUCCESS,任何错误都会引发异常

3)如果您有会话ID,请调用任何需要有效LDAP会话的过程,例如simple_bind_s并检查是否引发了invalid_session。如果您没有会话ID,我不知道确定是否有任何LDAP会话打开的方法。

答案 2 :(得分:2)

在我的应用程序中,我这样做:

ld := DBMS_LDAP.INIT(LDAP_SERVER, 389);
retval := DBMS_LDAP.SIMPLE_BIND_S(ld, LDAP_USER, LDAP_PASSWORD);
DBMS_LDAP.USE_EXCEPTION := FALSE;

retval := DBMS_LDAP.SEARCH_S(
    ld => ld, 
    base => LDAP_BASE,
    SCOPE => DBMS_LDAP.SCOPE_SUBTREE,
    FILTER => '&(objectCategory=user)(sAMAccountName='||username ||')', 
    attrs => attrs,
    attronly => 0,
    res => ldapMessage);
retval := DBMS_LDAP.COUNT_ENTRIES(ld, ldapMessage);
ldapEntry := DBMS_LDAP.FIRST_ENTRY(ld, ldapMessage);

IF ldapEntry IS NULL THEN
    retval := DBMS_LDAP.MSGFREE(ldapMessage);
    retval := DBMS_LDAP.UNBIND_S(ld);
    RAISE_APPLICATION_ERROR(-20001, 'User does not exist');
ELSE
    userDN := DBMS_LDAP.GET_DN(ld, ldapEntry);
END IF;
retval := DBMS_LDAP.MSGFREE(ldapMessage);


IF p_password IS NULL THEN
    retval := DBMS_LDAP.UNBIND_S(ld);
    RAISE_APPLICATION_ERROR(-20000, 'Invalid Null password');
ELSE
    retval := DBMS_LDAP.SIMPLE_BIND_S(ldapSession, userDN, p_password);
    IF retval <> DBMS_LDAP_UTL.SUCCESS THEN
        retval := DBMS_LDAP.UNBIND_S(ld);
        RAISE_APPLICATION_ERROR(-20001, 'Wrong password');
    END IF;
END IF;
retval := DBMS_LDAP.UNBIND_S(ld);

关于你的问题:

  

1)如何验证用户是否存在于Microsoft Active Directory

查看我的代码

  

所以第一个问题是userDNldapMessage

的价值

userDN将为NULL,ldapMessage我不在乎。

  

2)假设用户存在且输入了错误的密码,那将是retval的返回值

  • 有效密码:DBMS_LDAP.SUCCESS(0)
  • 错误的paasword:DBMS_LDAP.INVALID_CREDENTIALS(49)

注意,只有在设置DBMS_LDAP.INVALID_CREDENTIALS时才会获得DBMS_LDAP.USE_EXCEPTION := FALSE;,否则如果密码错误则会出现异常。

  

3)我的第三个问题是假设用户已登录系统并且ldapsession仍然没有解除绑定识别重复会话的方法

确保在您的代码中正确调用DBMS_LDAP.UNBIND_S(ld);

另一个警告:

如果您在DBMS_LDAP.SIMPLE_BIND_S(ldapSession, userDN, p_password);提供了错误的密码,则Active Directory中的badPwdCount属性会递增!因此,您可以无限制地尝试输入(或暴力破解)密码。