Oracle 19c调用Java存储过程遇PKCS11未找到错误求助
解决Oracle 19c Java存储过程中PKCS11提供器找不到的问题
我有一段从USB令牌读取证书的Java代码,本地独立运行正常,但通过loadjava导入Oracle 19c后执行时抛出:
java.security.KeyStoreException: PKCS11 not found
已在数据库主目录javavm文件夹下的java.security中添加security.provider.13=SunPKCS11 configration_file.cfg,但问题依旧。原代码如下:
class GetSignatureNew { public static void main(String args[]) { GetSignatureNew sdk = new GetSignatureNew(); } public static String GetSignatureFun(String serialized) { String pwd = "*******"; char[] pin = new char[pwd.length()]; try { for (int i = 0; i < pwd.length(); i++) { pin[i] = pwd.charAt(i); } // Get Certificate and private key from token KeyStore ks = KeyStore.getInstance("PKCS11"); ks.load(null, pin); Enumeration enu = ks.aliases(); String alias = String.valueOf(enu.nextElement()); X509Certificate cert = (X509Certificate) ks.getCertificate(alias); PrivateKey pk = (PrivateKey) ks.getKey(alias, pin); byte [] output = cert.getEncoded(); String b64 = Base64.getEncoder().encodeToString(output); return b64; } catch (Exception e) { e.printStackTrace(); return e.toString(); } } }
核心原因
Oracle数据库内嵌的JavaVM加载安全配置的逻辑和独立Java环境不同,直接修改javavm下的java.security可能未被生效,或者缺少必要的权限、路径配置。
解决步骤
1. 动态注册PKCS11提供器(最直接的修复方式)
绕过配置文件,在代码中手动注册SunPKCS11提供器,确保Oracle JVM能加载到:
public static String GetSignatureFun(String serialized) { String pwd = "*******"; char[] pin = pwd.toCharArray(); try { // 替换为PKCS11配置文件的绝对路径(数据库服务器本地路径) String pkcs11ConfigPath = "/opt/oracle/pkcs11/configration_file.cfg"; // 动态创建并添加PKCS11提供器 Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigPath); Security.addProvider(pkcs11Provider); // 指定使用刚注册的提供器获取KeyStore KeyStore ks = KeyStore.getInstance("PKCS11", pkcs11Provider); ks.load(null, pin); Enumeration<String> enu = ks.aliases(); String alias = enu.nextElement(); X509Certificate cert = (X509Certificate) ks.getCertificate(alias); PrivateKey pk = (PrivateKey) ks.getKey(alias, pin); byte[] output = cert.getEncoded(); String b64 = Base64.getEncoder().encodeToString(output); return b64; } catch (Exception e) { e.printStackTrace(); return e.toString(); } }
2. 验证PKCS11配置文件的正确性
确保configration_file.cfg包含正确的驱动路径和令牌信息,示例:
name=MyUSBToken library=/usr/lib64/libpkcs11.so # 替换为你的PKCS11驱动绝对路径 slot=0 # 令牌所在插槽,可根据实际情况调整
3. 检查Oracle进程的权限
- 确保Oracle数据库运行用户(通常是
oracle)对PKCS11驱动库和配置文件有读权限 - 确认USB令牌已在数据库服务器上正确识别,且Oracle进程能访问到令牌设备
4. 授予Java存储过程必要权限
执行SQL命令给用户授予安全权限:
-- 授予通用Java安全权限 GRANT JAVASECURITYPRIVILEGE TO your_database_user; -- 若需要访问文件系统,授予文件读写权限 CALL DBMS_JAVA.GRANT_PERMISSION('YOUR_DATABASE_USER', 'java.io.FilePermission', '/opt/oracle/pkcs11/*', 'read');
5. 确认Oracle JVM使用的安全配置文件路径
执行以下SQL查询,确认Oracle JVM实际加载的java.security文件路径,避免修改错文件:
SELECT DBMS_JAVA.GET_PROPERTY('java.security.properties') FROM DUAL;
如果查询结果显示自定义路径,需要修改对应路径下的配置文件,而非javavm目录下的默认文件。
内容的提问来源于stack exchange,提问作者Sameh Sewilam
相关产品推荐
相关产品推荐

