Twisted Python TLS 服务器:将客户端证书信息传递给资源/端点

Twisted Python TLS server : pass client certificate info to resource / endpoint

我正在尝试在 Twisted python 中实现带有 TLS 客户端证书的 XML-RPC 服务器。 此外,最终目标是只允许定义的用户列表(即证书列表)访问某些方法。

虽然我完成了第一部分,但我很难将证书信息传输到我计划应用过滤器的 XMLRPC.render_POST

我找到了 描述如何显示通用名称,但我仍然有两个问题:

  1. 来自客户端的XML-RPC调用在收到应答后没有return,我猜这意味着请求没有正确完成
  2. 我不知道如何将此信息进一步向下传递到 XMLRPC 资源

这是我目前的情况:

    import sys
    import OpenSSL
    from twisted.python.filepath import FilePath
    from twisted.internet import endpoints
    from twisted.internet import ssl
    from twisted.python import log
    from twisted.web import xmlrpc, server
    from twisted.internet.ssl import Certificate
    from twisted.internet.protocol import Protocol

    class ReportWhichClient(Protocol):
        # adapted from 
        def dataReceived(self, data):
            peerCertificate = Certificate.peerFromTransport(self.transport)
            print(peerCertificate.getSubject().commonName.decode('utf-8'))


    class Example(xmlrpc.XMLRPC):
        """
        An example object to be published.
        """

        def xmlrpc_echo(self, x):
            """
            Return all passed args.
            """
            return x


    def main():
        log.startLogging(sys.stdout)

        from twisted.internet import reactor

        key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM,FilePath("my.key").getContent())
        cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,FilePath("my.crt").getContent())
        ca = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, FilePath("ca.crt").getContent())
        contextFactory = ssl.CertificateOptions(privateKey=key, certificate=cert, verify=True, caCerts=[ca] , requireCertificate=True)

        root = Example()


        endpoint = endpoints.SSL4ServerEndpoint(reactor, 8083,contextFactory)
        mySite = server.Site(root)
        mySite.protocol = ReportWhichClient
        endpoint.listen(mySite)

        reactor.run()


    if __name__ == '__main__':
        main()

这是正确的做法吗?我应该怎么做才能在资源级别获得所需的信息?

任何答案都很好,此时我已经绞尽脑汁尝试了很多解决方案,但没有任何结果。

谢谢

好吧,解决方案一直摆在我面前。

重新阅读源代码后,似乎 transport 出现在请求中。我所要做的就是添加 @withRequest 装饰器并从那里获取所有信息:

class Example(xmlrpc.XMLRPC):

    @withRequest
    def xmlrpc_echo(self, request, x):
        peerCertificate = Certificate.peerFromTransport(request.transport)
        key = peerCertificate.getPublicKey().original
        # display the client public key in PEM format
        print(OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, key))
        return x