【问题标题】:How to use the MEMBER_OF2 function in Oracle Apex using the APEX_LDAP package如何使用 APEX_LDAP 包在 Oracle Apex 中使用 MEMBER_OF2 函数
【发布时间】:2021-10-16 11:54:17
【问题描述】:

由于我使用 LDAP 将我们的 Microsoft Active Directory 与我的 Apex 应用程序链接起来,我正在尝试为当前从 Active Directory 登录的用户检索组。

这是文档:https://docs.oracle.com/cd/E59726_01/doc.50/e39149/apex_ldap.htm#AEAPI242

这是我的页面加载动态操作的代码,我正在尝试检索当前用户所属的所有组的 VARCHAR2,并将其放在仅显示字段中:

BEGIN
    :P1_NEW := APEX_LDAP.MEMBER_OF2(
        p_username => v('APP_USER'),
        p_pass => 'mypassword',
        p_auth_base => 'DOMAIN\',
        p_host => 'XX.X.XXX.XX',
        p_port => 389);
END;

但是当我加载我的页面时,就会出现这个错误

Ajax 调用返回服务器错误 ORA-31202:DBMS_LDAP:错误的客户端/服务器 LDAP:无效的凭据。 80090308:LdapErr:DSID-0C090439,注释:AcceptSecurityContext 错误,数据 52e,v4563 用于执行 PL/SQL 代码。

我的代码有什么问题?提前感谢您的帮助。

托马斯

【问题讨论】:

  • 您使用的是什么版本的 APEX?安装apex的数据库是哪个版本?
  • 顺便说一句,我认为p_auth_base 的语法是错误的,因为您需要使用LDIF 格式的条目来查看。我已经为用户所属的密码验证 + 组成员配置了带有 LDAP 身份验证的 APEX。您提供的链接适用于 apex 5.0,这是一个非常过时的版本。
  • 您好 Roberto,我在 Apex v21.1 上,数据库是:Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
  • 我在 p_auth_base 上同意你的观点,这就是我不确定的,我已经尝试输入 dc=domain,dc=ch。但它不工作,仍然无效的凭据
  • 如果您使用相同的参数调用 APEX_LDAP.AUTHENTICATE,它是否有效?你能提供两者的输出吗??

标签: oracle plsql active-directory ldap oracle-apex


【解决方案1】:

我认为您使用了错误的 API 包 APEX_LDAP。我在自己的环境中以不同的方式执行此操作,但我使用的是企业版:

  1. Oracle 数据库版本 19c
  2. Oracle Apex 版本 20.1
  3. Oracle Oracle Rest 数据服务 20.4 版

我有一个身份验证架构来登录我自己公司的 LDAP 服务器。该身份验证架构替换了 Apex 本地管理的默认用户之一。

应用程序 --> 共享组件 --> 身份验证模式 --> 自定义

function fn_val_user_pwd_ldap (
    p_username in varchar2,
    p_password in varchar2
    )
return boolean
is
l_ldap_host  varchar2(100) := 'myldaphost.com';

l_ldap_port  number        := 389 ;
begin 
    if APEX_LDAP.AUTHENTICATE(
      p_username =>p_username,
      p_password =>p_password,
      p_search_base => 'OU=Users,OU=Mycompany,DC=de,DC=com,DC=corp',
      p_host => l_ldap_host,
      p_port => l_ldap_port) 
      then
            dbms_application_info.set_action(null);
            return true;
       else
            apex_util.set_authentication_result(p_code => 110);
            apex_util.set_custom_auth_status(p_status => 'Username or password incorrect.');
            dbms_application_info.set_action(null);
            return false; 
       end if;
end;

然后,我有一个使用相同身份验证方法的身份验证后过程来检索 LDAP 中的组。我更喜欢这种方式,因为它在身份验证后执行,但您也可以通过动态操作来执行此操作。

declare
    l_groups varchar2(4000);
BEGIN
    l_groups := APEX_LDAP.MEMBER_OF2(
        p_username => ':APP_USER',
        p_pass => 'mypassword',
        p_auth_base => 'OU=Users,OU=Mycompany,DC=de,DC=com,DC=corp',
        p_host => 'myldaphost.com',
        p_port => 389);
    htp.p('Is Member of:'||l_groups);
END;

我们不使用 SSL 与 LDAP 服务器进行内部通信,因为此应用程序是 Intranet。所以参数p_use_ssl默认为N。

正如我在您自己问题的评论部分告诉您的,我认为参数 p_auth_base 指的是您自己的 LDAP 服务器的 LDIF 格式,而不是指 AD 的域名。

更新

让我告诉你它是如何工作的。 (当然,我隐藏了自己公司的敏感信息)。有时可能会发生您无法将组信息设为空的情况。我不确定这里是否是 LDAP 授权问题,而不是 APEX 包本身的问题

SQL> SET SERVEROUTPUT ON SIZE UNLIMITED ECHO ON 
DECLARE
    is_ok        boolean;
    l_mes        varchar2(2000);
    l_val        varchar2(4000);
    l_ldap_host  varchar2(100) := 'myldapserver.com';
    l_ldap_port  number        := 389 ;
BEGIN
    if APEX_LDAP.AUTHENTICATE(
    p_username =>'X329097',
    p_password =>'********',
    p_search_base => 'OU=Users,OU=Mycompany,DC=****,DC=*****,DC=****,DC=corp',
    p_host => l_ldap_host,
    p_port => l_ldap_port ) 
    then
        is_ok := true;
        l_mes := 'Username and Password Correct' ;
        dbms_output.put_line(l_mes);
    else 
        l_mes := 'Username and Password Invalid' ;
        dbms_output.put_line(l_mes);
    end if;
    if is_ok 
    then 
        l_val := APEX_LDAP.MEMBER_OF2(
            p_username => 'X329097',
            p_pass => '*********',
            p_auth_base => 'OU=Users,OU=Mycompany,DC=****,DC=*****,DC=****,DC=corp',
            p_host => l_ldap_host,
            p_port => l_ldap_port);
        dbms_output.put_line(l_val);    
    end if;
END;
/

Username and Password Correct
SC_APEX_ADMIN:SC_ORACLE_ADMIN

PL/SQL procedure successfully completed.

【讨论】:

  • 我按照你说的试过了,我的“用户名和密码无效”
  • 以防万一,这是我创建的 ACL BEGIN DBMS_NETWORK_ACl_ADMIN.CREATE_ACL( acl => 'ldap', description => 'ldap host', principal => 'SYSTEM', is_grant => TRUE, privilege => 'connect' ); END; BEGIN DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL( acl => 'ldap', host => 'xx.x.xxx.xx', lower_port => 389 ); DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE( acl => 'ldap', principal => 'PUBLIC', is_grant => TRUE, privilege => 'connect' ); END;
【解决方案2】:

我尝试添加您的功能,但我无法再从我的登录页面访问我的应用程序。我已经尝试过 SQL 命令,这就是我得到的

DECLARE
VAL BOOLEAN;
BEGIN
IF APEX_LDAP.AUTHENTICATE(
    p_username => 'thomas.tirole',
    p_password => 'mypassword',
    p_search_base => 'OU=Users,OU=Domain,DC=domain,DC=ch',
    p_host => 'xx.x.xxx.xx',
    p_port => 389
) THEN
dbms_output.put_line('AUTENTHICATED');
ELSE
DBMS_OUTPUT.PUT_LINE('NOT AUTHENTICATED');
END IF;
END;

---------------------------------------

NOT AUTHENTICATED
Statement processed.
0.00 seconds

如果我尝试在 SQL 命令上执行 MEMBER_OF2 函数,这就是我得到的:

declare
    l_groups varchar2(4000);
BEGIN
    l_groups := APEX_LDAP.MEMBER_OF2(
        p_username => 'thomas.tirole',
        p_pass => 'mypassword',
        p_auth_base => 'OU=Users,OU=Domain,DC=domain,DC=ch', -- SAME WITH DOMAIN\
        p_host => 'xx.x.xxx.xx',
        p_port => 389);
    htp.p('Is Member of:'||l_groups);
END;

---------------------------------------

ORA-31202: DBMS_LDAP : Erreur client/serveur LDAP : Invalid credentials. 80090308: LdapErr: DSID-0C090439, comment: AcceptSecurityContext error, data 52e, v4563
ORA-06512: à "APEX_210100.WWV_FLOW_LDAP", ligne 508
ORA-06512: à "SYS.DBMS_SYS_ERROR", ligne 86
ORA-06512: à "SYS.DBMS_LDAP", ligne 1487
ORA-06512: à "SYS.DBMS_LDAP", ligne 79
ORA-06512: à "APEX_210100.WWV_FLOW_LDAP", ligne 85
ORA-06512: à "APEX_210100.WWV_FLOW_LDAP", ligne 172
ORA-06512: à "APEX_210100.WWV_FLOW_LDAP", ligne 214
ORA-06512: à "APEX_210100.WWV_FLOW_LDAP", ligne 235
ORA-06512: à "APEX_210100.WWV_FLOW_LDAP", ligne 464
ORA-06512: à "APEX_210100.WWV_FLOW_LDAP", ligne 523
ORA-06512: à ligne 4
ORA-06512: à "SYS.DBMS_SQL", ligne 1721

【讨论】:

  • 我很清楚您无法进行身份验证,因此程序首先失败了。你为什么使用名字和姓氏?在我的公司,我们总是使用 Active Directory 中的用户 ID,即您的 Windows 用户名
  • 您应该将其从答案部分中删除,并将其作为原始问题的更新。如果你支持我的回答,我真的很感激
  • 我可以进行身份​​验证,因为我可以使用 LDAP 目录预配置方案登录我的应用程序,并且“测试 LDAP 登录”工作正常。我正在使用我的 firstname.lastname,因为这是我在公司上制作凭据的方式,这是我用来连接 Windows 会话的方式。
  • 这就是为什么它绝对会破坏我的大脑,为什么我能够登录我的应用程序并验证测试 LDAP 登录,但为什么我无法在 APEX_LDAP 函数中进行身份验证
  • 嗨,托马斯。我不小心删除了我之前的评论,对不起。对于 apex_ldap.search,我的 p_search_base 是 'OU=Nederland,dc=my_comp,dc=com'。就这样。您的其余方法与我的方法相同。但是,我也无法让 member_of2 工作..
猜你喜欢
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-03
相关资源
最近更新 更多