【问题标题】:python ignore certificate validation urllib2python忽略证书验证urllib2
【发布时间】:2013-10-16 14:33:23
【问题描述】:

在我通过内部公司链接向服务器发出请求期间,我想忽略 certification validation

使用 python requests 库我会这样做:

r = requests.get(link, allow_redirects=False,verify=False)

如何对 urllib2 库做同样的事情?

【问题讨论】:

    标签: python python-2.7 urllib2 python-requests


    【解决方案1】:

    与此同时,urllib2 似乎默认验证服务器证书。 2.7.9 的 warning, that was shown in the past disappeared 我目前在使用自签名证书(和 Python 2.7.9)的测试环境中遇到了这个问题。

    我的 evil 解决方法(不要在生产中这样做!):

    import urllib2
    import ssl
    
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    
    urllib2.urlopen("https://your-test-server.local", context=ctx)
    

    According to docs 直接调用 SSLContext 构造函数也应该可以。我没试过。

    【讨论】:

    • 如此邪恶,如此有效xD感谢您。我已经陷入了绝望。
    • 看来ssl.create_default_context只有Python 3.4+才有。
    • 这适用于我使用 python 2.7.9(安装了 OSX Homebrew)谢谢!
    • 此解决方法不适用于 python 2.6.6 或 2.7.6。
    • 这个变通方法是完美的,但不要在 2.7.9 之前使用 context 参数调用 urllib2.urlopen() ,仅此而已。我在 2.7.10 和 2.6.x 中都使用它。使用以下代码检查版本:sys.version_info >= ( 2, 7, 9 )。
    【解决方案2】:

    最简单的方法:

    python 2

    import urllib2, ssl
    
    request = urllib2.Request('https://somedomain.co/')
    response = urllib2.urlopen(request, context=ssl._create_unverified_context())
    

    python 3

    from urllib.request import urlopen
    import ssl
    
    response = urlopen('https://somedomain.co', context=ssl._create_unverified_context())
    

    【讨论】:

    • 确保你有更高版本的python。 ubuntu 14.04 自带的版本不支持这种方式。
    • 此方法有效,但将导入语句更改为 from urllib.request import urlopen 而不是 import urllib2。有关更多信息,请参阅stackoverflow.com/questions/2792650/… 接受的答案。
    【解决方案3】:

    对于那些使用开瓶器的人,您可以根据 Enno Gröper 的出色回答来实现相同的目标:

    import urllib2, ssl
    
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    
    opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx), your_first_handler, your_second_handler[...])
    opener.addheaders = [('Referer', 'http://example.org/blah.html')]
    
    content = opener.open("https://localhost/").read()
    

    然后像以前一样使用它。

    根据build_openerHTTPSHandler,如果存在ssl模块,则添加一个HTTPSHandler,这里我们只指定我们自己的而不是默认的。

    【讨论】:

    • 好的调用,这看起来类似于本网站描述的方法。 thejosephturner.com/blog/post/…
    • 我不同意,恕我直言,这不相似。您提到的文章使用类扩展,而此方法使用香草实现并且仅使用 ssl 上下文。也就是说,您提到的文章对于想要更改和扩展默认 HTTPSHandler 行为的人来说是一个很好的观点。
    • 我明白你的意思,我没有注意到这种细微差别,你的绝对更干净,无需扩展任何东西。
    【解决方案4】:

    根据@Enno Gröper 的帖子,我尝试了 SSLContext 构造函数,它在我的机器上运行良好。代码如下:

    import ssl
    ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    urllib2.urlopen("https://your-test-server.local", context=ctx)
    

    如果您需要开瓶器,只需添加以下上下文:

    opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx))
    

    注意:以上测试环境均为python2.7.12。我在这里使用PROTOCOL_SSLv23,因为doc 这么说,其他协议也可能有效,但取决于您的机器和远程服务器,请查看文档以获取详细信息。

    【讨论】:

      【解决方案5】:

      一个更明确的示例,基于 Damien 的代码(调用 http://httpbin.org/ 的测试资源)。对于python3。请注意,如果服务器重定向到另一个 URL,add_password 中的 uri 必须包含新的根 URL(也可以传递 URL 列表)。

      import ssl    
      import urllib.parse
      import urllib.request
      
      def get_resource(uri, user, passwd=False):
          """
          Get the content of the SSL page.
          """
          uri = 'https://httpbin.org/basic-auth/user/passwd'
          user = 'user'
          passwd = 'passwd'
      
          context = ssl.create_default_context()
          context.check_hostname = False
          context.verify_mode = ssl.CERT_NONE
      
          password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
          password_mgr.add_password(None, uri, user, passwd)
      
          auth_handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
      
          opener = urllib.request.build_opener(auth_handler, urllib.request.HTTPSHandler(context=context))
      
          urllib.request.install_opener(opener)
      
          return urllib.request.urlopen(uri).read()
      

      【讨论】:

      • 感谢您使用标准库回答 python3 方式。准备上下文对我很有效。
      【解决方案6】:

      urllib2 默认不验证服务器证书。检查这个documentation.

      编辑:正如下面的评论所指出的,这对于 Python 的较新版本(似乎 >= 2.7.9)不再适用。参考以下ANSWER

      【讨论】:

      • 这似乎不再是真的了。
      • 确实不是这样了。
      • 那么,如果他当时的回答是正确的,为什么他会被否决?上课
      • “不再是真的” - 这完全没用。世界并没有神奇地升级他们的 Python 版本 - 实际上对于仍在使用 2.7.6 的任何人来说仍然如此!
      猜你喜欢
      • 2016-08-04
      • 1970-01-01
      • 2021-01-19
      • 2011-11-16
      • 2013-08-06
      • 1970-01-01
      • 2017-06-01
      • 2012-08-30
      • 2016-04-23
      相关资源
      最近更新 更多