使用Python oracledb连接Oracle遇SSL握手及连接关闭错误求助
Oracle数据库连接问题解决方案(Python 3.10.6 + oracledb + Django)
一、TCPS连接错误(DPY-6005: SSLV3_ALERT_HANDSHAKE_FAILURE)
该错误源于SSL握手协议不兼容,按以下步骤解决:
- 指定兼容SSL协议版本:
连接前配置SSL上下文,强制使用数据库支持的TLS版本(如TLSv1.2/TLSv1.3),示例代码:import ssl import oracledb # 创建并配置SSL上下文 ctx = ssl.create_default_context() ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 # 禁用旧版本TLS协议 ctx.set_ciphers('DEFAULT:@SECLEVEL=1') # 降低安全等级,避免证书兼容性冲突 # 构造包含SSL验证的连接字符串 cs = "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCPS)(HOST = hostname)(PORT = 1533)))(CONNECT_DATA = (SERVICE_NAME = service_name))(SECURITY=(SSL_SERVER_CERT_DN=\"CN=你的数据库证书DN\")))" c = oracledb.connect(user='username', password="password", dsn=cs, ssl_context=ctx) - 配置数据库证书:
若数据库要求验证证书,需将CA证书路径加载到SSL上下文:
若无需客户端证书验证,可在连接字符串中添加ctx.load_verify_locations(cafile="/path/to/root_ca.pem")(SECURITY=(SSL_CLIENT_AUTHENTICATION=FALSE))。
二、普通连接错误(DPY-4011: 数据库或网络关闭连接)
排查方向及解决方法:
- 验证网络连通性:
执行命令测试数据库端口是否可达:
若不通,联系管理员开放防火墙端口,或确认数据库主机地址无误。telnet dbhost.example.com 1984 # 或使用nc工具 nc -zv dbhost.example.com 1984 - 确认服务名正确性:
登录数据库服务器,执行lsnrctl status查看监听的服务名,确保代码中使用的SERVICE_NAME与监听输出一致。 - 切换oracledb运行模式:
oracledb默认使用纯Python实现的thin模式,若遇兼容性问题,切换到依赖Oracle客户端的thick模式:import oracledb # 初始化thick模式,需提前安装Oracle Instant Client oracledb.init_oracle_client(lib_dir="/path/to/oracle/instantclient") # 执行连接 connection = oracledb.connect(user="hr", password=userpwd, dsn="dbhost.example.com:1984/orclpdb")
三、Django应用中的连接配置
在settings.py的DATABASES中配置Oracle连接:
普通连接配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'orclpdb', # 对应数据库SERVICE_NAME 'USER': 'hr', 'PASSWORD': '你的密码', 'HOST': 'dbhost.example.com', 'PORT': '1984', } }
TCPS连接配置
通过OPTIONS传递自定义SSL上下文和连接字符串:
import ssl def get_ssl_context(): ctx = ssl.create_default_context() ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 ctx.load_verify_locations(cafile="/path/to/root_ca.pem") return ctx DATABASES = { 'default': { 'ENGINE': 'django.db.backends.oracle', 'USER': 'username', 'PASSWORD': 'password', 'OPTIONS': { 'dsn': "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCPS)(HOST = hostname)(PORT = 1533)))(CONNECT_DATA = (SERVICE_NAME = service_name))(SECURITY=(SSL_SERVER_CERT_DN=\"CN=你的数据库证书DN\")))", 'ssl_context': get_ssl_context(), }, } }
注意:Django 4.2+自带的Oracle后端已支持oracledb,低版本需安装django-oracle-backend依赖。
内容的提问来源于stack exchange,提问作者ThunderCloud
相关产品推荐
相关产品推荐

