离线Linux生产环境下Python连接公司SharePoint失败的解决方案问询
环境与问题描述
- 环境:处于离线状态的Linux生产环境,已配置代理;联网Windows环境可正常连接目标SharePoint站点
- 使用Python库:Office365-REST-Python-Client
- 核心错误:调用认证方法时无法连接
accounts.accesscontrol.windows.net,触发DNS解析失败(socket.gaierror: [Errno -2] Name or service not known),最终导致认证失败
相关代码
from office365.runtime.auth.authentication_context import AuthenticationContext from office365.sharepoint.client_context import ClientContext from urllib.parse import urlparse, quote, quote_plus SHAREPOINT_URL = "https://{tenant}.sharepoint.com" CLIENT_ID = "********" CLIENT_SECRET = "************" RELATIVE_URL = "/sites/Path" proxies = { "http": "http://{username@company.com}:quote_plus({password})@{server}:{port}", "https": "https://{username@company.com}:quote_plus({password})@{server}:{port}", } def __set_proxy(request): proxies = proxies request.proxies = proxies def __disable_ssl(request): request.verify = False def _auth() -> ClientContext: app = AuthenticationContext(SHAREPOINT_URL) app.acquire_token_for_app(CLIENT_ID, CLIENT_SECRET) ctx = ClientContext(SHAREPOINT_URL, app) ctx.pending_request().beforeExecute += __set_proxy ctx.pending_request().beforeExecute += __disable_ssl return ctx if __name__ == "__main__": ctx = _auth()
错误日志
Traceback (most recent call last): File "/opt/test_py39/lib/python3.9/site-packages/urllib3/connection.py", line 174, in _new_conn conn = connection.create_connection( File "/opt/test_py39/lib/python3.9/site-packages/urllib3/util/connection.py", line 72, in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): File "/opt/python_3.9.12/lib/python3.9/socket.py", line 954, in getaddrinfo for res in _socket.getaddrinfo(host, port, family, type, proto, flags): socket.gaierror: [Errno -2] Name or service not known ... requests.exceptions.ConnectionError: HTTPSConnectionPool(host='accounts.accesscontrol.windows.net', port=443): Max retries exceeded with url: /63ce7d59-2f3e-42cd-a8cc-be764cff5eb6/tokens/OAuth/2 (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f5c54b49970>: Failed to establish a new connection: [Errno -2] Name or service not known')) ... AttributeError: 'NoneType' object has no attribute 'text'
额外信息
- Linux环境中
ping {tenant}.sharepoint.com(不含协议和路径)可收到响应 ping {tenant}.sharepoint.com/site/Path和ping https://{tenant}.sharepoint.com均失败(注:ping无法解析带路径/协议的URL,此结果为正常现象)
排查与解决步骤
1. 修正代理配置的语法错误
当前代理配置存在两个问题:
- 直接写入
quote_plus({password})是字符串字面量,未实际执行URL编码 - 函数内重复定义
proxies = proxies会覆盖全局变量
修正后的代理配置:
from urllib.parse import quote_plus # 替换为实际代理参数 proxy_username = "username@company.com" proxy_password = "your_actual_password" proxy_server = "proxy.company.com" proxy_port = "8080" # 对密码进行URL编码(处理特殊字符) encoded_pwd = quote_plus(proxy_password) proxies = { "http": f"http://{proxy_username}:{encoded_pwd}@{proxy_server}:{proxy_port}", "https": f"https://{proxy_username}:{encoded_pwd}@{proxy_server}:{proxy_port}", } def __set_proxy(request): request.proxies = proxies # 直接使用全局代理配置
2. 调整认证与代理绑定的顺序
当前代码先执行认证,再绑定代理,导致认证请求未走代理。需先绑定代理,再触发认证:
def _auth() -> ClientContext: app = AuthenticationContext(SHAREPOINT_URL) ctx = ClientContext(SHAREPOINT_URL, app) # 先绑定代理和SSL设置 ctx.pending_request().beforeExecute += __set_proxy ctx.pending_request().beforeExecute += __disable_ssl # 再执行认证操作 app.acquire_token_for_app(CLIENT_ID, CLIENT_SECRET) return ctx
3. 确保代理允许访问Azure AD认证端点
错误中无法访问的accounts.accesscontrol.windows.net是SharePoint应用权限认证的核心端点,需:
- 用
curl -x https://{proxy_server}:{proxy_port} https://accounts.accesscontrol.windows.net测试代理是否允许访问该域名 - 如果DNS解析失败,从Windows环境用
nslookup accounts.accesscontrol.windows.net获取IP,手动添加到Linux的/etc/hosts文件中
4. 优化SSL验证配置(不建议直接禁用)
直接禁用SSL验证存在安全风险,若公司代理使用自签名证书,应指定CA证书路径:
def __disable_ssl(request): # 替换为公司内部CA证书的实际路径 request.verify = "/opt/company_certs/root_ca.crt"
5. 验证基础网络连通性
- 测试代理访问SharePoint站点:
curl -x https://{proxy_server}:{proxy_port} https://{tenant}.sharepoint.com - 检查Linux DNS配置:查看
/etc/resolv.conf,确保DNS服务器能正常解析Office 365相关域名
内容的提问来源于stack exchange,提问作者code_adithya
相关产品推荐
相关产品推荐

