如何使用Snap检查客户端证书

时间:2013-03-19 02:43:15

标签: haskell ssl haskell-snap-framework happstack

我知道它很少使用,但可以在Snap中访问客户端证书吗?

如果没有,是否可以使用不同的网络堆栈?

1 个答案:

答案 0 :(得分:1)

Snap的snap-server软件包无法使用此功能,我假设您正在运行服务器。

Buuuuut通过分叉或作为单独的模块构建并不困难(但是,您必须复制一些代码,因为您需要的某些内部值不会被导出)。 bindHttpslocated in Snap.Internal.Http.Server.TLS是您要定位的内容。这个函数主要是从HsOpenSSL库调用OpenSSL.Session的包装器,它本身是OpenSSL库的一个松散的包装器。

幸运的是,OpenSSL完全支持客户端证书。您只需将verification mode设置为SSL_VERIFY_PEER即可。你还可以摆弄其他旋钮。您还必须确保安装证书链以实际验证客户端证书。信任链和所有爵士乐。有关参考,请参阅nginx does it

更好的是,HsOpenSSL中的此函数为exposed,函数为contextSetVerificationMode :: SSLContext -> VerificationMode -> IO ()。您会注意到Snap ctx :: SSLContext的定义中存在bindHttps。您所要做的就是复制或分叉该模块并介绍您的电话。

它看起来像这样(未经验证的代码警报):

± % diff -u /tmp/{old,new}
--- /tmp/old    2016-04-11 11:02:42.000000000 -0400
+++ /tmp/new    2016-04-11 11:02:56.000000000 -0400
@@ -19,6 +19,7 @@

      ctx <- SSL.context
      SSL.contextSetPrivateKeyFile ctx key
+     SSL.contextSetVerificationMode ctx (SSL.VerifyPeer True True (Just (\_ _ -> return True)))
      if chainCert
        then SSL.contextSetCertificateChainFile ctx cert
        else SSL.contextSetCertificateFile ctx cert

如果没有客户端证书,则第一个布尔值告诉OpenSSL失败。第二个布尔值告诉OpenSSL,客户端证书仅在第一个请求时需要,在重新协商时不再需要。第三个值是回调。我认为正确的做法是在回调中返回True。无论如何,这都是nginx does