簡體   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