Python 2.7使用oauth2client获取GCP认证令牌时遇SSL错误
Python 2.7下使用oauth2client获取GCP Bearer令牌报错的解决方法及替代方案
问题背景
由于google-auth库不支持Python 2.7,需使用oauth2client复现google-auth的令牌获取逻辑,但运行代码时出现错误:cannot set verify_mode to CERT_NONE when check_hostname is enable。
报错原因
该错误是因为httplib2在启用disable_ssl_certificate_validation=True时,仅将SSL验证模式设为CERT_NONE,但未关闭check_hostname,两者冲突导致报错。
解决方案1:手动配置SSL上下文修复httplib2问题
直接创建自定义SSL上下文,同时关闭check_hostname和证书验证,替代httplib2自带的参数:
from oauth2client.service_account import ServiceAccountCredentials import httplib2 import ssl def get_token(serviceAccountPath, authTarget, proxy_url, proxy_port): credentials = ServiceAccountCredentials.from_json_keyfile_name( serviceAccountPath, scopes=[authTarget] ) # 创建自定义SSL上下文,同时关闭主机名检查和证书验证 ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE # 初始化Http对象,传入自定义SSL上下文和代理信息 http = httplib2.Http( proxy_info=httplib2.ProxyInfo( httplib2.socks.PROXY_TYPE_HTTP, proxy_url, proxy_port ), ssl_context=ssl_context ) http_auth = credentials.authorize(http) credentials.refresh(http_auth.request) return credentials.access_token
解决方案2:改用requests作为传输层
和google-auth的实现逻辑对齐,用requests替代httplib2,通过自定义适配器解决SSL验证问题:
from oauth2client.service_account import ServiceAccountCredentials import requests from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.ssl_ import create_urllib3_context import ssl class SSLNoVerifyAdapter(HTTPAdapter): def init_poolmanager(self, *args, **kwargs): # 创建禁用证书验证和主机名检查的SSL上下文 context = create_urllib3_context() context.check_hostname = False context.verify_mode = ssl.CERT_NONE kwargs['ssl_context'] = context super(SSLNoVerifyAdapter, self).init_poolmanager(*args, **kwargs) def get_token(serviceAccountPath, authTarget, proxy_url, proxy_port): credentials = ServiceAccountCredentials.from_json_keyfile_name( serviceAccountPath, scopes=[authTarget] ) # 配置requests会话,设置代理 session = requests.Session() session.proxies = { 'http': f'http://{proxy_url}:{proxy_port}', 'https': f'http://{proxy_url}:{proxy_port}' } # 挂载自定义适配器,处理HTTPS请求的SSL验证 session.mount('https://', SSLNoVerifyAdapter()) # 使用session的request方法完成令牌刷新 credentials.refresh(session.request) return credentials.access_token
替代方案:调用gcloud命令行工具获取令牌
如果环境已安装Google Cloud SDK(gcloud),可以直接调用命令行工具获取令牌,无需依赖oauth2client:
import subprocess def get_token_via_gcloud(): # 调用gcloud命令获取默认应用凭据的访问令牌 token_result = subprocess.check_output( ['gcloud', 'auth', 'application-default', 'print-access-token'], stderr=subprocess.STDOUT ) # 处理输出,返回纯令牌字符串 return token_result.strip().decode('utf-8')
注意事项
- 需确保环境已配置gcloud,且默认应用凭据有效(可通过
gcloud auth application-default login或设置GOOGLE_APPLICATION_CREDENTIALS环境变量完成配置)。
内容的提问来源于stack exchange,提问作者JayEstrera
相关产品推荐
相关产品推荐

