Oracle PL/SQL LDAP - 无法打开钱包
我尝试使用PL/SQL在Windows服务器上的Oracle 11g上运行的应用程序在内部针对SSL安全的LDAP服务器进行身份验证。我已将证书加载到钱包中并存储在d:\ wallets \中,并且可以验证它是否在oracle钱包管理器中有效/加载(ewallet.p12将打开,并显示我配置正确的密码)。但是,无论我做什么,我都无法使用PL/SQL函数来工作。下面是代码:Oracle PL/SQL LDAP - 无法打开钱包
create or replace FUNCTION ldap_auth(
p_username IN VARCHAR2,
p_password IN VARCHAR2
)
RETURN varchar2 IS
l_ldap_host VARCHAR2(256) := 'ldapserver.internal.net';
l_ldap_port number := 636;
l_dn VARCHAR2(512);
l_retval PLS_INTEGER;
l_session DBMS_LDAP.session;
l_wallet_loc varchar2(256) := 'file:D:\wallets';
l_wallet_pwd varchar2(256) := 'pa55w0rd';
l_wallet_ssl number := 3;
BEGIN
DBMS_LDAP.USE_EXCEPTION := TRUE;
l_dn := 'cn='||p_username||',ou=People,dc=internal,dc=net';
BEGIN
l_session := DBMS_LDAP.init(l_ldap_host, l_ldap_port);
EXCEPTION
when others then
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
RETURN 'exception1';
END;
BEGIN
l_retval := DBMS_LDAP.open_ssl (l_session, l_wallet_loc, l_wallet_pwd, l_wallet_ssl);
EXCEPTION
when others then
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
RETURN 'exception2';
END;
BEGIN
l_retval := DBMS_LDAP.simple_bind_s(l_session, l_dn, p_password);
EXCEPTION
when others then
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
RETURN 'exception3';
END;
return 'pass';
END;
而这里发生了什么,当我运行它:
select ldap_auth('userID','userPassword') as results1 from dual
ORA-20001:遇到一个错误 - -31202 -ERROR- ORA-31202:DBMS_LDAP:LDAP客户端/服务器错误:无法打开钱包 ORA-06512:在“DBUSERNAME.LDAP_AUTH”,第33行
我被困在这一点上,我无法找到任何参考线上如何使这项工作。
您可以尝试在l_wallet_ssl
的声明中使用pls_integer
而不是number
。另外,考虑从open_ssl
函数调用中删除when others exception
以查看是否可以获得更有用的错误(请参阅表4-86,了解来自this link的错误范围)。
IDK,如果你设法解决这个问题,但这里是我的答案基于深入分析和大量关于同一问题的谷歌搜索。我正在尝试创建用于SSL连接到AD服务器的PL/SQL函数。
1)我认为你说的问题,将与此解决:因为你全自动拿到这些赠款
CREATE DIRECTORY mydir AS 'D:\wallets';
授予READ在这种情况下写的是没有必要的。 但是你会在这之后遇到其他问题。这将是
ORA-31202: DBMS_LDAP: LDAP client/server error: SSL handshake failed
2)如果你正在使用11克DB和微软AD服务器的最新版本中,你将无法通过SSL连接来连接到广告,因为Oracle数据库中使用的密码。他们必须匹配DB和AD服务器中的bouth,但Oracle使用旧的和恕我直言不安全的密码。 他们解决了这个问题,部分在12c link到文档12c
2)我在11g中设法解决这个问题的唯一方法是通过Java。 解决方案是这样的:
SET SERVEROUTPUT ON;
CALL dbms_java.set_output(1000);
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED LDAP AS
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
public class ldap {
public static boolean ldap_auth(String username, String password, String ldap_server, String application) throws SQLException, ClassNotFoundException, UnknownHostException{
String keystore = "D:\\wallets";
System.setProperty("javax.net.ssl.trustStore", keystore);
System.setProperty("javax.net.ssl.trustStorePassword", "password");
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:SID", "USER", "password");
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldap_server);
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, username);
env.put(Context.SECURITY_CREDENTIALS, password);
InetAddress addr;
addr = InetAddress.getLocalHost();
String ip = addr.getHostAddress();
try {
DirContext ctx = new InitialDirContext(env);
System.out.println("Connection Successful!");
ctx.close();
return true;
} catch (Exception e) {
String errorMsg = e.toString();
String[] errorCode = {"data 525", "data 773", "data 52e", "data 775", "data 701", "data 533", "data 532"};
String returnErrorCode = null;
List<String> list = Arrays.asList(errorCode);
for(String word : list){
if(errorMsg.contains(word)) {
returnErrorCode = word;
}
}
CallableStatement procin = conn.prepareCall("begin prc_log_action_java (:1,:2,:3,:4); end;");
username = username.substring(0, username.indexOf('@'));
procin.setString(1, username);
procin.setString(2, returnErrorCode);
procin.setString(3, ip);
procin.setString(4, application);
procin.execute();
procin.close();
System.out.println(errorMsg);
return false;
}
}
};
尝试捕捉部分是用于记录由我赶上,并要求匿名块和插入表AD服务器生成的错误消息,我觉得你不需要这个代码,只是为情况。 errorCode字段列出了由AD服务器link to AD error codes生成的一些错误代码。
之后,你需要在数据库创建PL/SQL函数是这样的:
create or replace function ldap_auth (p_username in varchar2, p_password in varchar2, p_ldap_server in varchar2)return boolean
as language java
name 'ldap.ldap_auth (java.lang.String, java.lang.String, java.lang.String, java.lang.String) return boolean';
最后一件事是重要的是DB补助premissions。
call dbms_java.grant_permission('USER', 'SYS:java.net.SocketPermission', 'AD server:636', 'connect,resolve');
exec dbms_java.grant_permission('USER', 'SYS:java.util.PropertyPermission', 'javax.net.ssl.keyStore', 'write');
exec dbms_java.grant_permission('USER', 'SYS:java.util.PropertyPermission', 'javax.net.ssl.trustStorePassword', 'write');
commit;
哇,这比我本来希望得到的解决方案要好得多 - 我今天晚些时候会给出这个答案。谢谢! – kagaku
还有一件事,我希望你使用orapki实用工具正确创建钱包[链接到示例](https://docs.oracle.com/cd/E29542_01/core.1111/e10105/walletmgr.htm#ASADM10183) – n33l1x