Python连接SharePoint 2019报SSL验证失败如何正确禁用SSL校验
问题表现
使用office365Python库连接本地部署的SharePoint 2019时,自行编写的禁用SSL校验逻辑未生效,触发证书验证失败报错。同一份代码连接SharePoint Online可正常运行,仅连接SharePoint 2019时失败。
原测试代码
from office365.runtime.auth.authentication_context import AuthenticationContext from office365.sharepoint.client_context import ClientContext from office365.sharepoint.files.file import File import os import requests def disable_ssl(request): request.verify = False app_settings = { 'url': 'https://mysp.com/sites/'+'sitenameGG'+'/', 'client_id': 'xxxx', 'client_secret': 'xxxx', } context_auth = AuthenticationContext(app_settings['url']) context_auth.acquire_token_for_app(client_id=app_settings['client_id'], client_secret=app_settings['client_secret']) ctx = ClientContext(app_settings['url'], context_auth) web = ctx.web ctx.load(web) ctx.pending_request().beforeExecute += disable_ssl ctx.execute_query() response = File.open_binary(ctx, "/sites/sitenameGG/"+('some%20test%20lib/hello.csv')) with open(r'C:\Users\somepath\'+filename, 'wb') as local_file: local_file.write(response.content)
报错回溯
Traceback (most recent call last): File "C:\Python310\lib\urllib3\connectionpool.py", line 703, in urlopen httplib_response = self._make_request( File "C:\Python310\lib\urllib3\connectionpool.py", line 386, in _make_request self._validate_conn(conn) File "C:\Python310\lib\urllib3\connectionpool.py", line 1042, in _validate_conn conn.connect() File "C:\Python310\lib\urllib3\connection.py", line 414, in connect self.sock = ssl_wrap_socket( File "C:\Python310\lib\urllib3\util\ssl_.py", line 449, in ssl_wrap_socket ssl_sock = _ssl_wrap_socket_impl( File "C:\Python310\lib\urllib3\util\ssl_.py", line 493, in _ssl_wrap_socket_impl return ssl_context.wrap_socket(sock, server_hostname=server_hostname) File "C:\Python310\lib\ssl.py", line 512, in wrap_socket return self.sslsocket_class._create( File "C:\Python310\lib\ssl.py", line 1070, in _create self.do_handshake() File "C:\Python310\lib\ssl.py", line 1341, in do_handshake self._sslobj.do_handshake() ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Python310\lib\requests\adapters.py", line 440, in send resp = conn.urlopen( File "C:\Python310\lib\urllib3\connectionpool.py", line 786, in urlopen retries = retries.increment( File "C:\Python310\lib\urllib3\util\retry.py", line 592, in increment raise MaxRetryError(_pool, url, error or ResponseError(cause)) urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='mysp.somesiteGG.com', port=443): Max retries exceeded with url: /sites/somesiteGG/ (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)'))) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Python310\lib\office365\runtime\auth\providers\acs_token_provider.py", line 41, in get_app_only_access_token realm = self._get_realm_from_target_url() File "C:\Python310\lib\office365\runtime\auth\providers\acs_token_provider.py", line 70, in _get_realm_from_target_url response = requests.head(url=self.url, headers={'Authorization': 'Bearer'}) File "C:\Python310\lib\requests\api.py", line 102, in head return request('head', url, **kwargs) File "C:\Python310\lib\requests\api.py", line 61, in request return session.request(method=method, url=url, **kwargs) File "C:\Python310\lib\requests\sessions.py", line 529, in request resp = self.send(prep, **send_kwargs) File "C:\Python310\lib\requests\sessions.py", line 645, in send r = adapter.send(request, **kwargs) File "C:\Python310\lib\requests\adapters.py", line 518, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='mysp.somesiteGG.com', port=443): Max retries exceeded with url: /sites/somesiteGG/ (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)'))) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\G14826\PycharmProjects\pythonProject\access_rest.py", line 22, in <module> context_auth.acquire_token_for_app(client_id=app_settings['client_id'], client_secret=app_settings['client_secret']) File "C:\Python310\lib\office365\runtime\auth\authentication_context.py", line 82, in acquire_token_for_app return self._provider.ensure_app_only_access_token() File "C:\Python310\lib\office365\runtime\auth\providers\acs_token_provider.py", line 36, in ensure_app_only_access_token self._cached_token = self.get_app_only_access_token() File "C:\Python310\lib\office365\runtime\auth\providers\acs_token_provider.py", line 45, in get_app_only_access_token self.error = e.response.text AttributeError: 'NoneType' object has no attribute 'text' Process finished with exit code 1
故障原因
- 你写的
disable_ssl钩子只绑定了ClientContext实例的请求执行事件,但SSL报错发生在更早的令牌获取阶段:调用acquire_token_for_app时,库内部直接调用原生requests.head请求站点获取realm信息,这一步完全没走你绑定钩子的请求链路,所以设置的verify=False根本没生效。 - 最后抛出的
AttributeError是office365库本身的兼容bug:捕获到SSL异常时,异常对象没有response属性,库直接读取e.response.text触发了二次报错,把最初的SSL证书错误掩盖了。 - SharePoint 2019作为本地部署版本,大多使用自签名证书或企业内部CA签发的证书,不在Python默认的信任根证书列表里,所以会触发
unable to get local issuer certificate错误。
修复方案
- 在所有业务逻辑前全局禁用requests的SSL校验,同时关闭urllib3的SSL警告,覆盖令牌获取阶段的原生requests请求:
import urllib3 # 关闭SSL警告 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) import requests # 全局替换requests会话的request方法,默认关闭SSL校验 _old_session_request = requests.Session.request def _new_session_request(self, *args, **kwargs): kwargs.setdefault('verify', False) return _old_session_request(self, *args, **kwargs) requests.Session.request = _new_session_request
- 移除原来的
beforeExecute绑定的disable_ssl方法,直接给ClientContext的待执行请求设置关闭SSL校验:
ctx = ClientContext(app_settings['url'], context_auth) ctx.pending_request().verify = False
- 修复原代码里的路径拼接语法错误,不要直接用字符串拼接Windows路径,改用
os.path.join避免转义问题:
filename = "hello.csv" local_save_path = os.path.join(r"C:\Users\somepath", filename) with open(local_save_path, 'wb') as local_file: local_file.write(response.content)
注意:生产环境不推荐长期禁用SSL校验,更稳妥的方案是将SharePoint站点使用的根证书导出,导入到系统信任存储或Python的certifi证书库中,从根源解决证书信任问题。
内容的提问来源于stack exchange,提问作者Dixxyyy
相关产品推荐
相关产品推荐

