zoukankan      html  css  js  c++  java
  • Python sll

    import urllib2
    urllib2.urlopen('https://xxxx.com')

    本来这段代码很简单的,就是请求一个https的连接,可是报以下错误:

    urllib2.URLError:

    第一反应是https证书问题产生的,如是以'python ssl' 为关键字google后,看到大家都在用'requests'这个python组件做http请求客户端,就像java里面的httpclient组件一样,如果安装完request包后,改成如下代码:

    import requests
    requests.get('https://xxx.com')

     还是报以下错误:

    requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:140773E8:SSL routines:SSL23_GET_SERVER_HELLO:reason(1000)

    可以看出来,用requests和urllib2报的错误信息是一样,可见它们都是基于相同的底层api操作的,比如基于TLS的socket连接。到这里的时候我怀疑这个问题不是python代码写的有问题,可能是操作系统级别的设置错了。如下直接在shell客户端运行如下测试脚本:

    wget https://xxx.com

    果然报如下错误:

    OpenSSL: error:140773E8:SSL routines:SSL23_GET_SERVER_HELLO:reason(1000)
    无法建立 SSL 连接。

    到这里我怀疑是openssl安装有问题,更新到最新版本后还是一样,然后在浏览器里访问是可以的,所以应该不是openssl有问题。继续google.......,就发现有人也遇到过这种问题,说是连接SSL服务器时SSL的版本不对,如是用如下代码测试不同的SSL版本,看是不是这个问题:

    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代码了。、

    class MyAdapter(HTTPAdapter):
        def init_poolmanager(self, connections, maxsize):
            self.poolmanager = PoolManager(num_pools=connections,
                maxsize=maxsize,
                ssl_version=ssl.PROTOCOL_SSLv3)
     
    = requests.Session()
    s.mount('https://', MyAdapter())#所有的https连接都用ssl.PROTOCOL_SSLV3去连接
    s.get('https://xxx.com')
    urllib2实现:
    # 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__":
        = urllib2.urlopen("https://ui2web1.apps.uillinois.edu/BANPROD1/bwskfcls.P_GetCrse")
        print(r.read())

    可以看到这两种方案的原理都是一样,就是自定义连接处理器,改变连接时ssl的版本号。

  • 相关阅读:
    import()函数
    node-sass安装报错
    npm 安装扩展模块时,因缓存报错的问题汇总
    测试
    export default 和 export 区别
    正则
    物联网
    第十二次课堂总结
    第十二次作业
    作业10
  • 原文地址:https://www.cnblogs.com/zhaobang/p/7045455.html
Copyright © 2011-2022 走看看