使用CherryPy实现的双向SSL认证

8

从CherryPy 3.0版本开始,可以通过指向服务器证书和私钥来简单地启用单向SSL,如下所示:

import cherrypy

class HelloWorld(object):
    def index(self):
        return "Hello SSL World!"
    index.exposed = True

cherrypy.server.ssl_certificate = "keys/server.crt"
cherrypy.server.ssl_private_key = "keys/server.crtkey" 
cherrypy.quickstart(HelloWorld())

这使得客户端可以验证服务器的真实性。有没有人知道CherryPy是否支持双向ssl,例如,服务器也可以通过验证客户端证书来检查客户端的真实性?
如果是,能否给出一个例子如何实现?或者提供一个示例的参考文献?
3个回答

4

这个功能不是开箱即用的,您需要对wsgiserver进行补丁以提供该功能。目前正在进行一个票据(和补丁)http://www.cherrypy.org/ticket/1001


2
现在在https://bitbucket.org/cherrypy/cherrypy/issue/1001/adding-support-for-client-certificate。 - Pim

3
我一直在寻找相同的东西。我知道CherryPy网站上有一些补丁。
我还在CherryPy SSL客户端验证中发现了以下内容。我还没有将其与CherryPy补丁进行比较,但也许这些信息会有所帮助。
我们最近需要开发一个快速而弹性的REST应用程序,并发现CherryPy比其他Python网络框架(如Twisted)更适合我们的需求。不幸的是,它的简单性缺少一个我们需要的关键功能,即服务器/客户端SSL证书验证。因此,我们花了几个小时编写了一些快速修改当前版本3.1.2的代码段。以下是我们进行的修改:
cherrypy/_cpserver.py

@@ -55,7 +55,6 @@ instance = None ssl_certificate = None ssl_private_key
= None
+ ssl_ca_certificate = None nodelay = True

def __init__(self):

cherrypy/wsgiserver/__init__.py

@@ -1480,6 +1480,7 @@
# Paths to certificate and private key files ssl_certificate = None ssl_private_key = None
+    ssl_ca_certificate = None

def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None, max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5):

@@ -1619,7 +1620,9 @@

self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) if self.nodelay: self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-        if self.ssl_certificate and self.ssl_private_key:
+        if self.ssl_certificate and self.ssl_private_key and \
+            self.ssl_ca_certificate:
+ if SSL is None: raise ImportError("You must install pyOpenSSL to use HTTPS.")

@@ -1627,6 +1630,11 @@ ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.use_privatekey_file(self.ssl_private_key) ctx.use_certificate_file(self.ssl_certificate)
+            x509 = crypto.load_certificate(crypto.FILETYPE_PEM,
+                open(self.ssl_ca_certificate).read())
+            store = ctx.get_cert_store()
+            store.add_cert(x509)
+            ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, lambda *x:True) self.socket = SSLConnection(ctx, self.socket) self.populate_ssl_environ()

上述补丁需要在CherryPy服务器配置中包含一个新的配置选项server.ssl_ca_certificate。此选项标识连接客户端将被验证的证书颁发机构文件,如果客户端未提供有效的客户端证书,则会立即关闭连接。我们的解决方案有优点和缺点,主要优点是如果连接的客户端没有提供有效证书,则其连接将立即关闭。这对于安全问题很好,因为它不允许客户端访问CherryPy应用程序堆栈。然而,由于限制是在套接字级别上完成的,因此CherryPy应用程序永远无法看到连接的客户端,因此该解决方案有些不灵活。最佳解决方案将允许客户端连接到CherryPy套接字并将客户端证书发送到应用程序堆栈。然后,自定义的CherryPy工具将在应用程序堆栈内验证证书,并在必要时关闭连接;不幸的是,由于CherryPy的pyOpenSSL实现结构,很难在应用程序堆栈内检索客户端证书。当然,以上补丁应仅在您自己的风险下使用。如果您有更好的解决方案,请告诉我们。

0
如果当前版本的CherryPy不支持客户端证书验证,可以配置CherryPy监听127.0.0.1:80,安装HAProxy监听443并验证客户端证书,并将流量转发到127.0.0.1:80。 HAProxy简单、轻便、快速、可靠。 HAProxy配置示例

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接