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

Python 3.11调用API时遇SSLV3_ALERT_HANDSHAKE_FAILURE问题求助

问题:Python 3.11升级后SSL握手失败问题

将Python环境从3.8升级至3.11后,调用外部API时出现SSLV3_ALERT_HANDSHAKE_FAILURE错误,此前3.8版本可正常运行。错误发生在发起POST请求时,所用函数代码如下:

def get_gush_helka_api(city,street,home_number):
    headers = {
    }
    if pd.isna(city) or pd.isna(street):
        return None
    city = city.strip()
    street = street.strip()
    home_number = str(home_number).strip()

    address = f"{city} {street} {home_number}" if home_number else f"{city} {street}"
    json_data = {
        'whereValues': [
            address,
        ],
        'locateType': 2,
    }
    result = {}

    retries = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
    adapter = HTTPAdapter(max_retries=retries)
    session = requests.Session()
    session.mount('https://', adapter)
    try:
        response = requests.post('https://ags.govmap.gov.il/Search/ParcelLocate', headers=headers, json=json_data)
        if response.status_code == 200:
            json_obj = response.json()
            if json_obj['errorCode'] == 0 and json_obj['status'] == 0:
                try:
                    result = {
                        'gush': int(json_obj['data']['ResultData']['Values'][0]['Values'][0]),
                        'helka': int(json_obj['data']['ResultData']['Values'][0]['Values'][1]),
                    }
                except:
                    result = {
                        'gush':0,
                        'helka':0,
                    }
            return result
    except requests.exceptions.RequestException as e:
        print(f"An error occurred with {e}")

    return None

咨询问题

  1. Python 3.11是否存在已知的SSL/TLS兼容性问题?
  2. 如何修改代码以修复SSLV3_ALERT_HANDSHAKE_FAILURE错误,同时保持连接安全?
  3. 在Python 3.11中能否指定SSL/TLS协议版本或密码套件以适配服务器要求?

回答

1. Python 3.11的SSL/TLS兼容性问题

Python 3.11默认搭配的OpenSSL版本通常比3.8更高(如1.1.1n+或3.x分支),高版本OpenSSL会废弃老旧、不安全的TLS协议(TLS 1.0、1.1)和弱密码套件。如果目标API服务器仅支持这些被废弃的配置,就会触发握手失败。另外,Python 3.11对SSL上下文的默认配置更严格,禁用了部分兼容性较弱的算法,也可能导致与旧服务器的握手不兼容。

2. 修复错误的代码修改方案

核心是调整SSL上下文,在安全前提下兼容服务器配置,避免过度放宽安全规则。可以通过自定义SSLContext并挂载到requests会话实现:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import ssl
from requests.packages.urllib3.poolmanager import PoolManager
import pandas as pd

class TLSAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        # 创建基础SSL上下文
        ctx = ssl.create_default_context()
        # 启用TLS 1.2(根据服务器实际支持版本调整,优先保留TLS 1.2+)
        ctx.options &= ~ssl.OP_NO_TLSv1_2
        # 设置兼容的密码套件(可根据服务器支持情况调整)
        ctx.set_ciphers('ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384')
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            ssl_context=ctx
        )

def get_gush_helka_api(city,street,home_number):
    headers = {}
    if pd.isna(city) or pd.isna(street):
        return None
    city = city.strip()
    street = street.strip()
    home_number = str(home_number).strip()

    address = f"{city} {street} {home_number}" if home_number else f"{city} {street}"
    json_data = {
        'whereValues': [address],
        'locateType': 2,
    }
    result = {}

    retries = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
    session = requests.Session()
    # 挂载自定义TLS适配器,同时配置重试规则
    session.mount('https://', TLSAdapter(max_retries=retries))
    try:
        response = session.post('https://ags.govmap.gov.il/Search/ParcelLocate', headers=headers, json=json_data)
        if response.status_code == 200:
            json_obj = response.json()
            if json_obj['errorCode'] == 0 and json_obj['status'] == 0:
                try:
                    result = {
                        'gush': int(json_obj['data']['ResultData']['Values'][0]['Values'][0]),
                        'helka': int(json_obj['data']['ResultData']['Values'][0]['Values'][1]),
                    }
                except:
                    result = {'gush':0, 'helka':0}
            return result
    except requests.exceptions.RequestException as e:
        print(f"An error occurred with {e}")

    return None

注意事项:

  • 先用openssl s_client -connect ags.govmap.gov.il:443命令确认服务器支持的TLS版本,优先使用TLS 1.2+,避免启用已被淘汰的TLS 1.0/1.1。
  • 密码套件需匹配服务器实际支持的列表,不要使用已标记为不安全的套件。

3. Python 3.11中指定SSL/TLS协议版本或密码套件

完全可以,通过ssl.create_default_context()创建上下文后,可进行以下调整:

  • 指定协议版本:通过ctx.options启用/禁用特定协议,例如允许TLS 1.2:ctx.options &= ~ssl.OP_NO_TLSv1_2;若服务器支持TLS 1.3,Python 3.11搭配的高版本OpenSSL默认已启用,无需额外配置。也可通过ctx.set_alpn_protocols(['http/1.1'])设置ALPN协议。
  • 指定密码套件:使用ctx.set_ciphers()方法,传入符合OpenSSL格式的套件字符串,例如ctx.set_ciphers('ECDHE-RSA-AES256-GCM-SHA384'),可用openssl ciphers命令查看本地支持的套件列表。

另外,requests还支持通过verify参数指定CA证书、cert参数提供客户端证书,这些配置与协议/套件设置相互独立。

内容的提问来源于stack exchange,提问作者user21181082

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:10:35