更新:与 jython 2.7b1 中的错误相关的问题。请参阅错误报告:http ://bugs.jython.org/issue2021 。jython-coders 正在努力修复!
从 Jython2.5.3 更改为 jython2.7beta1 后,我不再能够使用 SSL、http 和“信任所有证书”读取网页内容。https 页面的响应始终为空字符串,从而导致 Jython 中 httplib.py 的 httplib.BadStatusLine 异常。
我需要能够从需要身份验证的网页中读取,并且不想设置任何证书存储,因为我必须具有可移植性。因此我的解决方案是使用http://tech.pedersen-live.com/2010/10/trusting-all-certificates-in-jython/提供的优秀实现
下面详细介绍示例代码。Twitter 可能不是最好的例子,因为它不需要证书信任;但无论有没有装饰器,结果都是一样的。
#! /usr/bin/python
import sys
from javax.net.ssl import TrustManager, X509TrustManager
from jarray import array
from javax.net.ssl import SSLContext
class TrustAllX509TrustManager(X509TrustManager):
# Define a custom TrustManager which will blindly
# accept all certificates
def checkClientTrusted(self, chain, auth):
pass
def checkServerTrusted(self, chain, auth):
pass
def getAcceptedIssuers(self):
return None
# Create a static reference to an SSLContext which will use
# our custom TrustManager
trust_managers = array([TrustAllX509TrustManager()], TrustManager)
TRUST_ALL_CONTEXT = SSLContext.getInstance("SSL")
TRUST_ALL_CONTEXT.init(None, trust_managers, None)
# Keep a static reference to the JVM's default SSLContext for restoring
# at a later time
DEFAULT_CONTEXT = SSLContext.getDefault()
def trust_all_certificates(f):
# Decorator function that will make it so the context of the decorated
# method will run with our TrustManager that accepts all certificates
def wrapped(*args, **kwargs):
# Only do this if running under Jython
if 'java' in sys.platform:
from javax.net.ssl import SSLContext
SSLContext.setDefault(TRUST_ALL_CONTEXT)
print "SSLContext set to TRUST_ALL"
try:
res = f(*args, **kwargs)
return res
finally:
SSLContext.setDefault(DEFAULT_CONTEXT)
else:
return f(*args, **kwargs)
return wrapped
#@trust_all_certificates
def read_page(host):
import httplib
print "Host: " + host
conn = httplib.HTTPSConnection(host)
conn.set_debuglevel(1)
conn.request('GET', '/example')
response = conn.getresponse()
print response.read()
read_page("twitter.com")
这导致:
Host: twitter.com
send: 'GET /example HTTP/1.1\r\nHost: twitter.com\r\nAccept-Encoding: identity\r\n\r\n'
reply: ''
Traceback (most recent call last):
File "jytest.py", line 62, in <module>
read_page("twitter.com")
File "jytest.py", line 59, in read_page
response = conn.getresponse()
File "/Users/erikiveroth/Workspace/Procera/sandbox/jython/jython2.7.jar/Lib/httplib.py", line 1030, in getresponse
File "/Users/erikiveroth/Workspace/Procera/sandbox/jython/jython2.7.jar/Lib/httplib.py", line 407, in begin
File "/Users/erikiveroth/Workspace/Procera/sandbox/jython/jython2.7.jar/Lib/httplib.py", line 371, in _read_status
httplib.BadStatusLine: ''
改回 jython2.5.3 为我提供了来自 twitter 的可解析输出。
你们中有人见过吗?在 jython 项目页面上找不到任何关于此的错误票,我也无法理解哪些更改可能导致此行为(可能超过 #1309,但我不明白它是否与我的问题有关)。
干杯