如何强制Python使用TLSv1.2向CUCM v10.0发送API请求?
解决Python强制指定TLS版本访问CUCM API的问题
问题描述
我可通过Postman成功向CUCM(Cisco Unified Communications Manager)v10.0服务器的API发送请求,支持TLSv1.2、TLSv1.1或TLSv1协议,但使用Python或CURL发送请求时,始终采用SSLv3协议,触发错误:requests.exceptions.SSLError: HTTPSConnectionPool(...) [SSL: SSLV3_ALERT_ILLEGAL_PARAMETER]。环境为Ubuntu 22.04、Python 3.10,尝试多种代码配置后问题仍未解决,需实现强制Python使用指定TLS版本发送请求。
尝试过的代码示例
示例1(requests基础调用)
import requests url = "https://172.25.0.6:8443/axl/" headers = { 'Content-Type': 'text/plain', 'Authorization': 'Basic token=', 'Cookie': 'JSESSIONID=DCCokiee; JSESSIONIDSSO=SessionId' } payload = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns=\"http://www.cisco.com/AXL/API/10.0\"> <soapenv:Header /> <soapenv:Body> <ns:executeSQLQuery sequence=\"?\"> <sql>select first 10 * from numplan where dnorpattern='3335610'</sql> </ns:executeSQLQuery> </soapenv:Body> </soapenv:Envelope>" response = requests.get(url, headers=headers) if response.status_code == 200: print("Success!") print(response.text) else: print("Unsuccess. HTTP Kodu:", response.status_code) response = requests.request("POST", url, headers=headers,auth=("username","password"), data=payload) print(response.text)
示例2(http.client+ssl上下文)
import socket import ssl import http.client # Set your API endpoint and parameters hostname = '172.25.0.6' port = 8443 endpoint = '/axl' api_url = f'https://{hostname}:{port}{endpoint}' # Create an SSL context that enforces TLSv1.2 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.options |= ssl.OP_NO_SSLv3 context.options |= ssl.OP_NO_TLSv1 context.options |= ssl.OP_NO_TLSv1_1 # context.maximum_version = ssl.TLSVersion.TLSv1_3 ciphers = [ 'AES256-SHA', 'AES128-SHA', ] context.set_ciphers(':'.join(ciphers)) # Your API request headers and payload headers = { 'Content-Type': 'text/xml', 'Authorization': 'Basic RmFyaWQ2MTI6RmFyaWQ2MTI=' } conn = http.client.HTTPSConnection(hostname, port, context=context) conn.request('POST', endpoint, body=payload, headers=headers)
解决方案
方法1:自定义requests适配器强制指定TLS版本
通过自定义HTTPAdapter,给requests会话绑定指定TLS版本的SSL上下文,彻底规避SSLv3:
import requests import ssl from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager class TLSAdapter(HTTPAdapter): def init_poolmanager(self, connections, maxsize, block=False): # 强制使用TLSv1.2,禁用低版本协议 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.options |= ssl.OP_NO_SSLv3 context.options |= ssl.OP_NO_TLSv1 context.options |= ssl.OP_NO_TLSv1_1 # 配置CUCM支持的加密套件 context.set_ciphers('AES256-SHA:AES128-SHA') self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, ssl_context=context ) # 初始化会话并挂载适配器 session = requests.Session() session.mount('https://', TLSAdapter()) # 请求参数调整(修复Content-Type为CUCM要求的text/xml) url = "https://172.25.0.6:8443/axl/" headers = { 'Content-Type': 'text/xml', 'Authorization': 'Basic 你的Base64编码凭证' } payload = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/10.0"> <soapenv:Header /> <soapenv:Body> <ns:executeSQLQuery sequence="?"> <sql>select first 10 * from numplan where dnorpattern='3335610'</sql> </ns:executeSQLQuery> </soapenv:Body> </soapenv:Envelope>""" try: # 自签证书场景添加verify=False,生产环境建议导入证书到信任库 response = session.post(url, headers=headers, data=payload, verify=False) response.raise_for_status() print("请求成功!") print(response.text) except requests.exceptions.RequestException as e: print(f"请求失败:{e}")
方法2:环境变量临时配置
不想修改代码时,可通过环境变量强制Python使用指定加密套件和禁用SSLv3:
# 指定CUCM支持的加密套件 export SSL_CIPHERS="AES256-SHA:AES128-SHA" # 自签证书场景关闭验证(生产环境慎用) export PYTHONHTTPSVERIFY=0
执行上述命令后再运行Python脚本即可。
关键注意事项
- 必须将
Content-Type设置为text/xml,CUCM AXL API不支持text/plain类型,这是之前请求可能失败的原因之一。 - 自签证书场景下使用
verify=False仅用于测试,生产环境需将CUCM证书导入Ubuntu系统信任库。 - 优先使用
auth=("username", "password")让requests自动处理Base64授权,避免手动编码出错。
内容的提问来源于stack exchange,提问作者Fərid Həbibli
相关产品推荐
相关产品推荐

