今天写代码时碰到一个问题,花了几个小时的时间google,
首先需要安装openssl,更新到最新版本后,在浏览器里看是否可访问,如果是可以的,所以应该不是openssl有问题。
然后使用 curl尝试访问
https://ui2web1.apps.uillinois.edu/BANPROD1/bwskfcls.P_GetCrse
可以查看ssl版本,如果不能访问,尝试更换ssl版本
1 2 3 4 5 | curl -1 https: //xxx .com curl -2 https: //xxx .com curl -3 https: //xxx .com |
分别用上面的三句脚本去测试连接情况,发现第三种可以连接正常(-1,2,3,数字分别代码tlsv1,sslv2,sslv3三个不同的SSL版本)。说明这个https连接所在的服务器是基于SSLV3版本的。找到的问题,就很容易知道怎么改写Python代码了。
1 2 3 4 5 6 7 8 9 | class MyAdapter(HTTPAdapter): def init_poolmanager( self , connections, maxsize): self .poolmanager = PoolManager(num_pools = connections, maxsize = maxsize, ssl_version = ssl.PROTOCOL_SSLv3) s = requests.Session() s.mount( 'https://' , MyAdapter()) #所有的https连接都用ssl.PROTOCOL_SSLV3去连接 s.get( 'https://xxx.com' ) |
urllib2实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # custom HTTPS opener, banner's oracle 10g server supports SSLv3 only import httplib, ssl, urllib2, socket class HTTPSConnectionV3(httplib.HTTPSConnection): def __init__( self , * args, * * kwargs): httplib.HTTPSConnection.__init__( self , * args, * * kwargs) def connect( self ): sock = socket.create_connection(( self .host, self .port), self .timeout) if self ._tunnel_host: self .sock = sock self ._tunnel() try : self .sock = ssl.wrap_socket(sock, self .key_file, self .cert_file, ssl_version = ssl.PROTOCOL_SSLv3) except ssl.SSLError, e: print ( "Trying SSLv3." ) self .sock = ssl.wrap_socket(sock, self .key_file, self .cert_file, ssl_version = ssl.PROTOCOL_SSLv23) class HTTPSHandlerV3(urllib2.HTTPSHandler): def https_open( self , req): return self .do_open(HTTPSConnectionV3, req) # install opener urllib2.install_opener(urllib2.build_opener(HTTPSHandlerV3())) if __name__ = = "__main__" : r = urllib2.urlopen( "https://ui2web1.apps.uillinois.edu/BANPROD1/bwskfcls.P_GetCrse" ) print (r.read()) |
可以看到这两种方案的原理都是一样,就是自定义连接处理器,改变连接时ssl的版本号。