You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:25:39