在撰写本文时,使用 Oracle 的 mysql-connector-python 2.1.4 纯 python 模块(您使用的是版本 2.1.3 的一个分支)支持连接字符串中未记录的连接配置 kwarg ssl_cipher (因为它基本上将它传递给 python 的 ssl 模块)。因此,从密码列表中删除所有 Diffie-Hellman 密码,您可能能够解决此问题,具体取决于您的 mysql 服务器是否支持非 Diffie-Hellman 密码。以下适用于官方 Python 2.7.12 amd64 win32 针对 MySQL 5.6.17-65.0-rel65.0-log 。 注意:这仅适用于处理 pure python 版本的模块!。如果使用编译好的C扩展模块,可能不接受ssl_cipher, YMMV。
import mysql.connector
import getpass
dsn = {
'database': 'INFORMATION_SCHEMA',
'host': 'mysqlserver',
'port': '3306',
'ssl_ca': '',
# ^^^ this sets cert_reqs = ssl.CERT_NONE
# in mysql/connector/network.py:415
# so no server cert verification is attempted
'use_pure': True
# setting ssl_cipher may only work with the pure python driver
# but this is the default anyway
}
dsn['user'] = raw_input('Enter Username: ')
dsn['password'] = getpass.getpass('Enter password: ')
try:
dbconn = mysql.connector.connect(**dsn)
# this will raise the 'Weak DH key' exception
except mysql.connector.errors.InterfaceError as e:
print e
dsn['ssl_cipher'] = 'HIGH:!DH:!aNULL'
# this is a standard openssl ciphersuite string
# where !DH and !aNULL means don't use any DH ciphers or null ciphers
# this option is officially undocumented
try:
dbconn = mysql.connector.connect(**dsn)
except mysql.connector.errors.InterfaceError:
raise
else:
assert isinstance(dbconn, mysql.connector.connection.MySQLConnection)
香肠的制作方法
在 mysql-connector-python 2.1.4 中,模块源代码中的以下行显示了它是如何工作的:
mysql/connector/abstracts.py: Lines 298 - 313:
for key, value in config.items():
try:
DEFAULT_CONFIGURATION[key]
except KeyError:
raise AttributeError("Unsupported argument '{0}'".format(key))
# SSL Configuration
if key.startswith('ssl_'):
set_ssl_flag = True
self._ssl.update({key.replace('ssl_', ''): value})
else:
attribute = '_' + key
try:
setattr(self, attribute, value.strip())
except AttributeError:
setattr(self, attribute, value)
然后在mysql/connector/connection.py lines 130-134:
if client_flags & ClientFlag.SSL and ssl_options:
packet = self._protocol.make_auth_ssl(charset=charset,
client_flags=client_flags)
self._socket.send(packet)
self._socket.switch_to_ssl(**ssl_options)
_socket.switch_to_ssl() 位于mysql/connector/network.py lines 406-421:
def switch_to_ssl(self, ca, cert, key, verify_cert=False, cipher=None):
"""Switch the socket to use SSL"""
if not self.sock:
raise errors.InterfaceError(errno=2048)
try:
if verify_cert:
cert_reqs = ssl.CERT_REQUIRED
else:
cert_reqs = ssl.CERT_NONE
self.sock = ssl.wrap_socket(
self.sock, keyfile=key, certfile=cert, ca_certs=ca,
cert_reqs=cert_reqs, do_handshake_on_connect=False,
ssl_version=ssl.PROTOCOL_TLSv1, ciphers=cipher)
self.sock.do_handshake()