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

时间:2018-11-26 15:41:58

标签: python twisted xml-rpc

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

当我掌握了第一部分的内容时,我很难将证书信息向下传递到计划应用过滤器的XMLRPC.render_POST上。

我发现this answer描述了如何显示通用名称,但是我仍然有两个问题:

  1. 从客户端收到的XML-RPC调用在收到答案后没有返回,我想这意味着请求未正确完成
  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 https://stackoverflow.com/a/28682511
        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()

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

任何答案都将是一个不错的选择,在这一点上,我一直在绞尽脑汁尝试许多解决方案,但没有任何结果。

谢谢

1 个答案:

答案 0 :(得分:0)

好的,所以解决方案一直在我眼前。

重新阅读源代码后,请求中似乎存在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