安全连接到RPC服务器的方法

5 投票
1 回答
7041 浏览
提问于 2025-04-16 10:07

这个问题和如何处理Python xmlrpclib连接被拒绝有关。

当我尝试使用以下代码时,如果我的RPC服务器没有运行,_get_rpc()会返回False,这样我就可以继续了。但是如果服务器在运行,它会因为找不到方法而失败。这是不是在尝试对远程服务器执行.connect()?当我需要使用.connect()来检测返回的代理是否有效时,我该如何解决这个问题呢?(请参见相关问题)

import xmlrpclib
import socket

def _get_rpc():
    try:
        a = xmlrpclib.ServerProxy('http://dd:LNXFhcZnYshy5mKyOFfy@127.0.0.1:9001')
        a.connect()     # Try to connect to the server
        return a.supervisor
    except socket.error:
        return False


if not _get_rpc():
    print "Failed to connect"

这里是问题所在:

ahiscox@lenovo:~/code/dd$ python xmlrpctest2.py
Failed to connect
ahiscox@lenovo:~/code/dd$ supervisord -c ~/.supervisor # start up RPC server
ahiscox@lenovo:~/code/dd$ python xmlrpctest2.py
Traceback (most recent call last):
  File "xmlrpctest2.py", line 13, in <module>
    if not _get_rpc():
  File "xmlrpctest2.py", line 7, in _get_rpc
    a.connect()     # Try to connect to the server
  File "/usr/lib/python2.6/xmlrpclib.py", line 1199, in __call__
    return self.__send(self.__name, args)
  File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
    verbose=self.__verbose
  File "/usr/lib/python2.6/xmlrpclib.py", line 1253, in request
    return self._parse_response(h.getfile(), sock)
  File "/usr/lib/python2.6/xmlrpclib.py", line 1392, in _parse_response
    return u.close()
  File "/usr/lib/python2.6/xmlrpclib.py", line 838, in close
    raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault 1: 'UNKNOWN_METHOD'>

1 个回答

5

我刚刚在研究这个问题;我以前的方法不好,因为 xmlrpclib.ServerProxy 在你调用一个方法时才尝试连接到 XmlRPC 服务器,而不是提前连接!!!

不如试试这个:

import xmlrpclib
import socket

def _get_rpc():
    a = xmlrpclib.ServerProxy('http://dd:LNXFhcZnYshy5mKyOFfy@127.0.0.1:9001')

    try:
        a._()   # Call a fictive method.
    except xmlrpclib.Fault:
        # connected to the server and the method doesn't exist which is expected.
        pass
    except socket.error:
        # Not connected ; socket error mean that the service is unreachable.
        return False, None

    # Just in case the method is registered in the XmlRPC server
    return True, a

connected, server_proxy = _get_rpc():
if not connected
    print "Failed to connect"
    import sys
    sys.exit(1)

总结一下,我们有三种情况:

  1. XmlRPC 服务器正常运行,并且我们定义了一个叫 _() 的方法:
    (补充说明:我选择了这个名字 _,因为这个名字的方法不太可能存在,但这种情况还是有可能发生)
    在这种情况下,不会捕获到异常,代码会执行到 return True

  2. XmlRPC 服务器正常运行,但我们没有定义 _() 这个方法:
    这时会抛出 xmlrpclib.Fault 异常,但我们仍然会执行到 return True

  3. XmlRPC 服务器宕机:
    这时会抛出 socket.error 异常,当我们调用 a._() 时,所以我们应该 return False

我不知道有没有简单的方法来做到这一点,我很想看到,如果没有,希望这次能解决问题 :)

注意:当你使用 if a: 时,Python 会再次查找一个叫 __nonzero__() 的方法来测试 a 的布尔值,这样也会失败。

注意 2:一些 xmlrpc 服务提供专门用于身份验证的 rpc 路径,在这个路径下,服务提供像 login() 这样的函数,这种方法可以替代我们这里的 _() 方法,所以只要调用 login(),就足够知道服务是正常还是宕机(socket.error),同时如果服务正常,这个 login() 方法还会验证用户身份。

撰写回答