本文旨在解决在 Oracle 数据库中执行 Java 存储过程时遇到的 "java.security.KeyStoreException: PKCS11 not found" 错误。该错误通常发生在 Java 代码尝试访问 USB Token 中的证书时,表明 Java 虚拟机 (JVM) 无法找到或加载 PKCS11 安全提供程序。本文将提供详细的排查步骤和解决方案,包括配置 `java.security` 文件、检查 JVM 环境以及使用 Oracle Wallet Manager 等方法,以确保 Java 代码能够正确访问 PKCS11 设备。
当 Java 代码在 Oracle 数据库内部执行时,它运行在数据库服务器的 JVM 环境中。这个 JVM 环境可能与开发环境的 JVM 环境不同,导致在独立 Java 程序中正常工作的代码在 Oracle 数据库中运行时出现 java.security.KeyStoreException: PKCS11 not found 错误。 该错误表明 JVM 无法找到 PKCS11 提供程序,这通常是因为 java.security 配置文件未正确配置,或者 JVM 没有加载必要的 PKCS11 库。
以下是解决此问题的步骤:
java.security 文件用于配置 Java 安全属性,包括可用的安全提供程序。你需要确保 Oracle 数据库服务器的 JVM 使用的 java.security 文件包含了 PKCS11 提供程序的配置。
找到 java.security 文件:
编辑 java.security 文件:
security.provider.13=sun.security.pkcs11.SunPKCS11 config_file.cfg
s11.SunPKCS11: 指定 PKCS11 提供程序的类名。config_file.cfg 文件包含了 PKCS11 库的路径和其他配置信息。你需要根据你的 PKCS11 设备的具体情况创建此文件。
创建配置文件:
name = MyPKCS11 library = /path/to/pkcs11.dll # 替换为你的 PKCS11 库的实际路径 slotListIndex = 0 # 替换为你的 token 所在的 slot 索引
放置配置文件:
确保 Oracle 数据库服务器的 JVM 已经正确加载了 PKCS11 提供程序。
重启数据库实例:
验证提供程序是否加载:
import java.security.Provider;
import java.security.Security;
import java.sql.*;
public class ListProviders {
public static void listProviders() throws SQLException {
Provider[] providers = Security.getProviders();
for (Provider provider : providers) {
System.out.println("Provider: " + provider.getName() + ", Version: " + provider.getVersion());
}
}
}确保运行 Oracle 数据库的用户具有访问 PKCS11 库和 USB Token 的权限。
文件系统权限:
USB Token 权限:
Oracle Wallet Manager 可以用于管理安全证书和密钥。 你可以使用 Oracle Wallet Manager 将 USB Token 中的证书导入到 Oracle Wallet 中,然后使用 Oracle Wallet 中的证书进行签名。
创建 Oracle Wallet:
导入证书:
配置 Java 代码:
解决 Oracle 数据库中 Java 存储过程的 "java.security.KeyStoreException: PKCS11 not found" 错误需要仔细的配置和排查。 通过配置 java.security 文件,创建 PKCS11 配置文件,检查 JVM 环境,并确保正确的权限,你可以成功地解决此问题,并使你的 Java 代码能够正确访问 USB Token 中的证书。 如果问题仍然存在,请查阅 Oracle 数据库和 USB Token 厂商的文档,或寻求专业的技术支持。