繁体   English   中英

Python:将xmlrpc模块与需要身份验证的服务器一起使用

[英]Python: use xmlrpc module with a server requiring authentication

我想使用Python脚本查询XML-RPC服务器。

第一个障碍是服务器使用身份验证,因此我不得不诉诸request.Session来克服这一点。 现在,我可以了,我可以通过RPC查询服务器,但是我使用的是非常难看的机制-粘合字符串。 当然,这只会生成XML数据,我将不得不再次对其进行手动处理以将其转换为可用的列表或字典。

我发现有一个适用于Python的xmlrpc模块,它可以与服务器完美地协同工作; 但是,在使用XML-RPC之前,我找不到如何对自己进行身份验证。

这是我已经使用请求编写的代码:

from requests import Session

myserver_address='http://myserver.test.com/admin'
myserver_RPC=myserver_address+'?RPC2'
myserver_header={'Content-Type': "text/xml; charset=UTF-8"}
myserver_login={"srvAction":"LoginAdmin", "login":"testuser", "password":"testpassword", "Submit":"Login", "select_locale":"en"}
myserver_login2={"srvAction":"LoginOrg", "selectSection":"20", "submit":"Continue"}

method_header = '<methodCall xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions"><methodName>'
param_header = '</methodName><params>'
param_body_header = '<param><value><string>'
param_body_footer = '</string></value></param>'
method_footer = '</params></methodCall>'

def myserver_get_xml(myserver_method, myserver_method_param):
    param_body = ''

    for param in myserver_method_param:
        param_body = param_body + param_body_header + str(param) + param_body_footer

    myserver_post = method_header + myserver_method + param_header + param_body + method_footer
    page = s.post(myserver_RPC, myserver_post)
    return page.text

s = Session()
s.get(myserver_address)
s.post(myserver_address, myserver_login) 
s.post(myserver_address, myserver_login2)

s.headers.update(myserver_header)

result_xml = myserver_get_xml('myserverServer.getNetworkTree', ['31', ] )
print(result_xml)

所以问题是:

  • 如何在经过身份验证的会话中使用xmlrpc模块?

  • 如果这是不可能的,是否有什么不错的方法可以将XML转换为字典(最好是字典)或列表?

输出示例:

<?xml version="1.0" encoding="UTF-8"?><methodResponse xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions"><params><param><value><array><data><value><array><data><value>10.0.0.0/16</value><value><i4>1</i4></value><value>31</value></data></array></value><value><array><data><value>10.1.0.0/16</value><value><i4>2</i4></value><value>31</value></data></array></value></data></array></value></param></params></methodResponse>

您将需要实现自己的xmlrpclib.Transport类,并在实例化xmlrpclib.ServerProxy时将其指定为传输参数。 请参阅https://docs.python.org/2/library/xmlrpclib.html#example-of-client-usage上的代理传输实现示例。 您可能只需要实现和修改Transport.make_connection ,它需要返回一个httplib.HTTPConnection实例,该实例的cookie头从登录操作的http响应头中设置。 您不能真正使用Session类发出请求,因为它与其他Transport类方法使用的httplib.HTTPConnection类不兼容。 因此,为简单起见,您也许可以使用Session实例执行登录,提取标头(尤其是cookie标头),然后使用这些标头创建HTTPConnection。

def create_session_headers():
      s = requests.Session()
      # perform your request.Session creation with the login posts
      # return headers from the loggedin session
      return s.headers

class SessionTransport(xmlrpclib.Transport):
    def make_connection(self, host):
          # create the standard connection
          connection = super(SessionTransport, self).make_connection(host)
          session_headers = create_session_headers()
          for key, value in session_headers.items():
              connection.putheader(key, value)
          return connection

 service = xmlrpclib.ServerProxy(server_address, SessionTransport())

我不确定它是否会像这样工作,我还没有测试过。 我希望它能为您提供足够的信息来尝试这种方法。

前一阵子找到了解决方案,到目前为止工作正常。 它非常粗糙,不适合处理XML,但是由于我只需要从应用程序中获取一些数据,因此它可以工作。

#!/cygdrive/c/Python34/python.exe

from requests import Session
import sys
import json
import xmltodict

myserver_address='http://myserver.test.com/admin'
myserver_RPC=myserver_address+'?RPC2'
myserver_header={'Content-Type': "text/xml; charset=UTF-8"}
myserver_login={"srvAction":"LoginAdmin", "login":"testuser", "password":"testpassword", "Submit":"Login", "select_locale":"en"}
myserver_login2={"srvAction":"LoginOrg", "selectSection":"20", "submit":"Continue"}

s = Session()
s.get(myserver_address)
s.post(myserver_address, myserver_login) 
s.post(myserver_address, myserver_login2)

s.headers.update(myserver_header)

myserverMethod = '<methodCall xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions"><methodName>myserverMyViewUsage.getMyViewChildrenArray</methodName><params><param><value><int>602</int></value></param></params></methodCall>'
subnet_list = s.post(myserver_RPC, myserverMethod)
subnet_dictionary_coarse = xmltodict.parse(subnet_org_list.text)

#print( json.dumps(subnet_org_dictionary_coarse, indent=2))

for subnet_org_dictionary in subnet_org_dictionary_coarse['methodResponse']['params']['param']['value']['array']['data']['value']:
<put code here>

没错,这基本上是在强奸XML以获取我需要的数据。 这是一个“快速且非常肮脏”的hack。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM