Flask 的双向 SSL 认证

22 投票
1 回答
22832 浏览
提问于 2025-04-18 04:03

我已经实现了SSL通信,客户端应用程序通过flask验证SSL服务器应用程序的身份。现在我想让SSL服务器应用程序验证SSL客户端应用程序的身份。这在flask中可以做到吗?我该如何验证客户端证书?在第一次握手时,客户端会发送一个证书签名请求(CSR),然后我会回复一个由自签名CA证书签署的证书。

但是我还不清楚在下一次通信时,服务器是如何验证客户端的。有没有什么回调函数可以用来验证证书?在Google群组上的链接说,在Flask中无法进行SSL认证。为了做到这一点,需要使用像apache或nginx这样的网络服务器。这是唯一的客户端认证方式吗?

还有一件我想实现的事情,就是我需要根据每个客户端的证书来识别他们。这在flask中可能实现吗?

我的问题可能有点幼稚,因为我对flask还不太熟悉。

1 个回答

11

免责声明

在开始之前,我想提一下@Emanuel Ey的评论。首先,你需要考虑一下这是在生产服务器还是开发服务器上进行的。例如,如果你使用的是Apache Web服务器,HTTPS的部分可以通过Apache来处理。你唯一需要做的不同的是将证书的详细信息作为选项传递,然后你的服务器应用程序会在应用程序内部验证序列号。

这是可能的

不过,这种做法并不算是好的编程习惯。遗憾的是,这个功能在flask.request中无法直接访问,也不能通过Flask包实现。然而,Flask使用了Werkzeug,通过对werkzeug.serving包进行修改是可以实现的,而你会在这里编写主要的Flask代码。这样做不推荐,因为你可能以后想更新Flask或Werkzeug,而你的修改可能会失效,需要重新调整。比如说,从0.9版本更新到1.0版本。

这种方法可以在不使用网络服务器的情况下提供解决方案。但我建议使用网络服务器和环境变量的组合,这样更干净,也算是比较好的做法。

我做了一些测试,看看这个方法是否容易实现。我确认这个方法可以在最新的开发代码库 'Werkzeug-0.10_devdev_20141223-py2.7' 中工作。

你可能想要验证每个证书中的序列号(种子号),也许还需要验证其他一些变量。正如你所知道的,序列号是每个证书唯一的,并且是在你服务器端生成证书时确定的。为了后续验证客户端证书的序列号,建议将其与客户端记录和证书信息(在适当的情况下)一起存储。注意:这可能需要在十六进制和十进制之间进行转换。

Werkzeug dev_2014122

我所做的是在werkzeug.serving.BaseWSGIServer.__init__调用wrap_socket()时添加以下选项。

使用这些选项; server_side=True, ca_certs= '/etc/apache2/ssl/ca.pem', cert_reqs=ssl.CERT_REQUIRED

  • ca_certs:用来进行验证的,这是用于生成客户端证书的CA证书。
  • ssl.CERT_REQUIRED:要求对ca_certs进行客户端证书验证。

注意:如果客户端证书未通过初步验证,你将无法获取客户端证书。它将为None。

然后在我的Flask测试类中,我修改了verify_request,具体如下:

def verify_request(self, request, client_address):

cert = request.getpeercert(True)
raw = decoder.decode(cert)[0]
print "Serial Number of your certificate is: % " % str(raw[0][1])
# todo: do checks & if serial no is ok then return true
return True

werkzeug.serving.BaseWSGIServer.verify_request = verify_request

这证明了这是可能的,但你可能想要研究一下HTTPServer类的请求处理程序,BaseWSGIServer是从这个类继承的,以找到更好的回调或重写的方法。

Werkzeug 0.9.X

如果你使用的是Werkzeug 0.9.X,我假设你使用的是from OpenSSL import SSL。可以查看代码片段 这里。我没有测试过这个。

在这个版本中,你可能感兴趣的一些调用包括: - Context.set_verify(mode, callback) - Connection.get_peer_certificate()

澄清

我不太明白你提到的在第一次握手时发送CSR。如果这是你生成客户端证书的过程,你可能需要重新考虑一下在你的系统和环境中如何进行。如果我能得到更多信息,我可以进一步评论。

另外,在SSL/TLS的上下文中,“握手”通常指的是使用现有证书创建安全连接的动作。握手完成后,简单来说,连接就建立了。

撰写回答