首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python 3中基于HTTPS的XMLRPC服务器

Python 3中基于HTTPS的XMLRPC服务器
EN

Stack Overflow用户
提问于 2011-04-17 00:58:32
回答 2查看 5.3K关注 0票数 3

我试图在Python 3上实现一个简单的XML服务器,我希望它使用标准的ssl库(包含在Python2.6和Python3.x中)在HTTPS上运行。

我已经看到了一些使用OpenSSL或M2Crypto模块执行此操作的代码,但我希望避免任何依赖。

我实现了下一个代码,它应该将SSL协议封装在套接字上:

代码语言:javascript
复制
"""Monkey patching standard xmlrpc.server.SimpleXMLRPCServer
to run over TLS (SSL)

Changes inspired on http://www.cs.technion.ac.il/~danken/SecureXMLRPCServer.py
"""
import socket
import socketserver
import ssl
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCDispatcher, SimpleXMLRPCRequestHandler
try:
    import fcntl
except ImportError:
    fcntl = None


class SimpleXMLRPCServerTLS(SimpleXMLRPCServer):
    def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
                 logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
        """Overriding __init__ method of the SimpleXMLRPCServer

        The method is an exact copy, except the TCPServer __init__
        call, which is rewritten using TLS
        """
        self.logRequests = logRequests

        SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)

        """This is the modified part. Original code was:

            socketserver.TCPServer.__init__(self, addr, requestHandler, bind_and_activate)

        which executed:

            def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
                BaseServer.__init__(self, server_address, RequestHandlerClass)
                self.socket = socket.socket(self.address_family,
                                            self.socket_type)
                if bind_and_activate:
                    self.server_bind()
                    self.server_activate()

        """
        socketserver.BaseServer.__init__(self, addr, requestHandler)
        self.socket = ssl.wrap_socket(
            socket.socket(self.address_family, self.socket_type),
            server_side=True,
            cert_reqs=ssl.CERT_NONE,
            ssl_version=ssl.PROTOCOL_TLSv1,
            )
        if bind_and_activate:
            self.server_bind()
            self.server_activate()

        """End of modified part"""

        # [Bug #1222790] If possible, set close-on-exec flag; if a
        # method spawns a subprocess, the subprocess shouldn't have
        # the listening socket open.
        if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
            flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
            flags |= fcntl.FD_CLOEXEC
            fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)

但出于某种原因,我无法确定,这会导致这个错误:

代码语言:javascript
复制
[Errno 8] _ssl.c:502: EOF occurred in violation of protocol

在调用远程方法之前。

有没有人知道会发生什么,或者是否知道如何收集更多的信息,以获得关于问题所在的线索?

提前谢谢你!

更新:

已修复。代码中有两个错误。首先,必须指定证书文件(其中也可以包括密钥)。

第二,xmlrpc.client.ServerProxy (包含在Python中)使用SSLv2,因此TLSv1不能工作。

工作守则是:

代码语言:javascript
复制
"""Monkey patching standard xmlrpc.server.SimpleXMLRPCServer
to run over TLS (SSL)

Changes inspired on http://www.cs.technion.ac.il/~danken/SecureXMLRPCServer.py
"""
import socket
import socketserver
import ssl
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCDispatcher, SimpleXMLRPCRequestHandler
try:
    import fcntl
except ImportError:
    fcntl = None


class SimpleXMLRPCServerTLS(SimpleXMLRPCServer):
    def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
                 logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
        """Overriding __init__ method of the SimpleXMLRPCServer

        The method is an exact copy, except the TCPServer __init__
        call, which is rewritten using TLS
        """
        self.logRequests = logRequests

        SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)

        """This is the modified part. Original code was:

            socketserver.TCPServer.__init__(self, addr, requestHandler, bind_and_activate)

        which executed:

            def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
                BaseServer.__init__(self, server_address, RequestHandlerClass)
                self.socket = socket.socket(self.address_family,
                                            self.socket_type)
                if bind_and_activate:
                    self.server_bind()
                    self.server_activate()

        """
        socketserver.BaseServer.__init__(self, addr, requestHandler)
        self.socket = ssl.wrap_socket(
            socket.socket(self.address_family, self.socket_type),
            server_side=True,
            certfile='cert.pem',
            cert_reqs=ssl.CERT_NONE,
            ssl_version=ssl.PROTOCOL_SSLv23,
            )
        if bind_and_activate:
            self.server_bind()
            self.server_activate()

        """End of modified part"""

        # [Bug #1222790] If possible, set close-on-exec flag; if a
        # method spawns a subprocess, the subprocess shouldn't have
        # the listening socket open.
        if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
            flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
            flags |= fcntl.FD_CLOEXEC
            fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
EN

回答 2

Stack Overflow用户

发布于 2013-08-26 13:01:18

你为什么不像这样写:

代码语言:javascript
复制
server = SimpleXMLRPCServer(...)
...
server.socket = ssl.wrap_socket(srv.socket, ...)
server.serve_forever()
票数 2
EN

Stack Overflow用户

发布于 2011-04-17 05:32:57

将您的Python服务器移到像Apache、NGinx之类的反向代理之后,让反向代理到SSL job...this比在job...this级别上工作得更好、更顺畅。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5690733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档