前面我们说道很多的场景是需要客户端验证(Client Certificate)的,而python的web server如何支持呢?
大多数的python web server都是符合WSGI标准的,也就是他们提供WSGI标准支持的功能,也就是他们几乎都不支持WSGI不支持的功能。很遗憾,客户端验证不在此列。换句话说,Cherrypy,webpy等常用的python web server都无法支持客户端验证。
我终于找到了Twisted(他怎么一下从2.5就蹦到了8.0.1)的web模块可以作为一个单独的web server。而这个web模块是包装的很底层的,使用pyopenssl,并且不是WSGI的一个实现。也就是说,他很可能是支持客户端验证的。
经过一番google,发现了支持的办法。如下:
首先我们看一下如何让Twisted支持HTTPS,他需要执行reactor.listenSSL方法,
class Hello(Resource) :
isLeaf = True
def render(self, request) :
return ‘Hello, SSL’
root = server.Site(Hello())
ctxFactory = ssl.DefaultOpenSSLContextFactory(
‘/path/to/server.key’,
‘/path/to/server.crt’
)
reactor.listenSSL(443, root, contextFactory = ctxFactory)
reactor.run()
这是最基本的支持HTTPS的方法,我们看,他需要一个contextFactory,深入到Twisted里面发现这个contextFactory是SSL进行设置。我们想要他支持客户端验证,就要从这里下手了。
DefaultOpenSSLContextFactory的cacheContext方法是对context进行的操作。我们重写这个方法。
class SSLClientCertificateFactory(ssl.DefaultOpenSSLContextFactory) :
def __init__(self, privateKeyFileName, certificateFileName, sslmethod=SSL.SSLv23_METHOD) :
ssl.DefaultOpenSSLContextFactory.__init__(self, privateKeyFileName, certificateFileName, sslmethod)
def _verify(self, connection, x509, errnum, errdepth, ok):
“”"
print ‘_verify (ok=%d):’ % ok
print ‘ subject:’, x509.get_subject()
print ‘ issuer:’, x509.get_issuer()
print ‘ errnum %s, errdepth %d’ % (errnum, errdepth)
“”"
return ok
def cacheContext(self) :
ssl.DefaultOpenSSLContextFactory.cacheContext(self)
ctx = self._context
ctx.load_verify_locations(‘/path/to/ca.crt’)
ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self._verify)
self._context = ctx
我们在通过默认的contextFactory生成context之后,执行ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self._verify),这样就加入和客户端验证,并且在self._verify函数里面我们还可以具体的验证证书的情况。
改写最上面的程序,
class Hello(Resource) :
isLeaf = True
def render(self, request) :
return ‘Hello, SSL’
root = server.Site(Hello())
ctxFactory = SSLClientCertificateFactory(
‘/path/to/server.key’,
‘/path/to/server.crt’
)
reactor.listenSSL(443, root, contextFactory = ctxFactory)
reactor.run()
好了,此时我们的python web server已经支持客户端验证了
后记:这里我有一个思考,就是为什么WSGI(暂时)不支持客户端验证?我想应该不是设计者忽视了这个问题。一般的,需要客户端验证这样的应用场景,很难只是假设一个python的web server,前面应该都有一个Apache等纯粹的服务器,那么这些验证之类的工作完全交付给Apache就足够好了,python没必要自己来处理。也许这就是原因吧。
那么,从这里我们也能看出,作为一个纯粹的网络应用组件,Twisted至少从功能上还是非常强大的。
0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.