Python通过TCPS连接Oracle数据库

标签 python database oracle ssl tcpserver

尝试从 python 通过 TCPS 连接来连接 Oracle 数据库,但失败并显示 ORA-28759:无法打开文件。

我不确定从本地/其他服务器连接到不同服务器上的数据库时需要在钱包中配置什么。

    import os
    import os.path
    import sys
    import cx_Oracle

    ORACLE_VERSION=19.3
    os.environ['ORACLE_BASE']=/Users/machild/Documents/oracle
    os.environ['ORACLE_HOME']='$ORACLE_BASE/product/instantclient/$ORACLE_VERSION'
    os.environ['DYLD_LIBRARY_PATH']='$ORACLE_HOME/lib'
    os.environ['OCI_DIR']='$DYLD_LIBRARY_PATH'
    os.environ['TNS_ADMIN']='$ORACLE_BASE/network/admin'


    Connection_String ='username/password@(DESCRIPTION =(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCPS)(HOST=orclconsapp.vci.map.com)(PORT=1587)))(CONNECT_DATA = (SERVICE_NAME=cons_app)))'

    connection = cx_Oracle.connect(Connection_String)


    cursor = connection.cursor()
    cursor.execute("""select to_char(sysdate,'mm/dd/yyyy') from dual""")
    for result in cursor:
        print(result)

**Its failing with below error**

Traceback (most recent call last):
File "/Users/machild/Documents/oracle_conn.py", line 16, in <module>
connection = cx_Oracle.connect(Connection_String)
cx_Oracle.DatabaseError: ORA-28759: failure to open file


I think it would need a wallet but not sure what exactly goes in wallet if we want to connect from external server( not where database is running). Any ideas?        

最佳答案

我也遇到过ORA-28759。我正在使用 Python/SQLAlchemy 与需要 TCPS 的 Oracle 数据库进行通信。我的 DBA 给了我一个受信任的证书,我必须将其存储在钱包中。

tl;dr: 我使用 okapi 创建了一个钱包文件,将我的证书导入到该钱包中,然后编辑 sqlnet.ora 以包含钱包的位置。我使用 TNS_ADMIN 环境变量指向 sqlnet.ora。 (基本上就是 Christopher Jones 的建议。)由于您已经有了一个现有的 TNS_ADMIN,您可能只想编辑其中的 sqlnet.ora 以指向钱包,创建后。

以下是我的情况的详细信息,包括我如何创建钱包。我所做的结合了这些来源的信息:

  1. https://docs.oracle.com/cd/E11882_01/network.112/e40393/asoappf.htm#ASOAG9831

  2. https://docs.oracle.com/en/database/oracle/oracle-database/18/dbseg/configuring-authentication.html#GUID-3EA07020-A9F3-4FF9-9518-E1AEA3BDDBBE

  3. https://cx-oracle.readthedocs.io/en/latest/user_guide/initialization.html#optnetfiles

注意:以下详细信息基于 Windows!

我要做的第一件事就是创建一个新钱包。 docs.oracle.com 中的第一个 URL 描述了对我有用的命令:orapki。该工具来 self 本地安装的 Oracle XE 18c (Windows)。

要创建钱包,我输入:

orapki wallet -nologo create -wallet C:\Users\rick\wallet -auto_login

这创建了一个文件夹C:\Users\rick\wallet,其中包含四个文件:cwallet.sso、cwallet.sso.lck、ewallet.p12、ewallet.p12.lck。 cwallet.sso 是“自动登录钱包”,ewallet.p12 是 PKCS#12 钱包。 (更多详细信息请参阅文档。)注意:-auto_login 创建了一个不需要密码即可打开的钱包,尽管系统提示我输入密码。我设置了一个一次性密码,不需要再次使用它。

我尝试连接的 Oracle 数据库要求我的钱包包含可信证书。 orapki 具有 -trusted_cert 开关,允许我将其导入到我的钱包中。

orapki wallet -nologo add -wallet \Users\rick\wallet -cert \Users\rick\oracle-ca.pem -trusted_cert

我能够使用以下方法确认钱包包含证书:

orapki wallet -nologo display -wallet \Users\rick\wallet -complete

我的输出:

C:\Users\rick>orapki wallet -nologo display -wallet \Users\rick\wallet -complete
Requested Certificates:
User Certificates:
Trusted Certificates:
Subject:        CN=Redacted,OU=Oracle,O=Amazon Web Services\, Inc.,ST=Washington,L=Seattle,C=US
Issuer:         CN=Redacted,OU=Oracle,O=Amazon Web Services\, Inc.,ST=Washington,L=Seattle,C=US
Serial Number:  AA:C7:REDACTED:AE:75
Key Length      1024
MD5 digest:     66:EC:REDACTED:9F:0D
SHA digest:     D4:0D:REDACTED:3C:50:91

要使用这个钱包,您必须指向它。这对我来说涉及两个步骤。第一步是创建一个指向钱包的 sqlnet.ora 文件。第二步是将 TNS_ADMIN 环境变量设置为包含 sqlnet.ora 文件的目录。就我而言,sqlnet.ora 和钱包文件都位于同一目录中。

来自 docs.oracle.com 的第二个 URL 显示了如何在 sqlnet.ora 文件内指定钱包位置(目录)。我的 sqlnet.ora 文件包含:

SQLNET.AUTHENTICATION_SERVICES= (NTS)
NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)
WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=C:\Users\rick\wallet)))
SSL_CLIENT_AUTHENTICATION=FALSE

我从 Oracle 服务器的 network/admin 目录中获取了 sqlnet.ora。我将此文件复制到与我的钱包相同的目录中,然后对其进行编辑。为了更好地衡量,我还将 tnsnames.ora 文件从 network/admin 复制到钱包目录中,尽管我不需要编辑此文件。

最后,cx_Oracle 文档(第三个 URL)提供了最后的详细信息:如何将 cx_Oracle 指向此钱包。根据我的理解,您将cx_Oracle指向包含sqlnet.ora的目录,并且sqlnet.ora指向钱包目录。

文档说使用 cx_Oracle.init_oracle_client()config_dir 命名参数来指定 sqlnet.ora 文件的位置,但由于我使用的是 SQLAlchemy,所以我没有直接调用它。但是,文档表示默认情况下驱动程序将在几个标准位置查找 sqlnet.ora 文件,包括由 TNS_ADMIN 环境变量指定的目录。

我使用以下方式设置TNS_ADMIN:

set TNS_ADMIN=C:\Users\rick\wallet

然后,当我运行我的 Python 程序时,它成功了!

关于Python通过TCPS连接Oracle数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66094119/

相关文章:

javascript - PHP 和 JavaScript 结合在一起

php - 如何将这段代码转为sql删除函数?

java - Oracle 数据更改通知超时和工作流

Python 引发/捕获异常

python - 解析时获取空列表

python - 如何用最新的脚本重新加载 nginx?

sql - 动态 SQL 或 WITH 子句

python - 如何在Python退出时捕获信号并传递变量?

mysql - NodeJS 如何处理对 MySQL 的并发请求

regex - 在 Oracle 中,如何选择包含特定数字范围内的字符的行?