Преобразование команды cURL со строкой XML в запрос python - PullRequest
0 голосов
/ 26 апреля 2020

Я был использован для отправки XML строк в API моего брандмауэра с помощью этой команды cURL:

curl -k https://192.1.1.1:90/APIController -F "reqxml=<myfile.xml"

Теперь я хотел бы сделать это в python. Поскольку строка XML будет создаваться программно, я не предоставляю файл XML, а строку XML. Это мой код прямо сейчас:

#!/usr/bin/env python
import requests

def xml_string():
    return '''
    reqxml=<?xml version="1.0" encoding="UTF-8"?>
    <Request>
        <Login>
            <Username>admin</Username>
            <Password>admin</Password>
        </Login>
        <Set>
        … further markup …
        </Set>
    </Request>
    '''

def send_xml():
  response = requests.post(
    "https://192.1.1.1:90/APIController",
    headers={"Content-Type": "application/xml"},
    data=xml_string(),
    verify=False
    )
  print(response.status_code)


send_xml()

Вывод подробной команды curl -k -v https://192.1.1.1:90/APIController -F "reqxml=<testcategory.xml":

* Trying 192.1.1.1...
* TCP_NODELAY set
* Connected to 192.1.1.1 (192.1.1.1) port 90 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=NA …
*  start date: Aug  1 00:00:00 2010 GMT
*  expire date: Dec 31 23:59:59 2030 GMT
*  issuer: C=NA …
*  SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway.
> POST /APIController HTTP/1.1
> Host: 192.1.1.1:90
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 796
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------20be8a5c28d38998
> 
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Sun, 26 Apr 2020 10:07:59 GMT
< Server: xxxx
< X-Frame-Options: SAMEORIGIN
< Strict-Transport-Security: max-age=31536000
< X-Content-Type-Options: nosniff
< Content-Type: text/xml;  charset=UTF-8
< Cache-Control: max-age=2592000
< Expires: Tue, 26 May 2020 10:07:59 GMT
< Transfer-Encoding: chunked
< 
<?xml version="1.0" encoding="UTF-8"?>
<Response APIVersion="1702.1" IPS_CAT_VER="1">
  <Login>
    <status>Authentication Successful</status>
  </Login>
  <Status code="200">Configuration applied successfully.</Status>
</Response>
* Connection #0 to host 192.1.1.1 left intact

Но несмотря на то, что возвращенный код состояния равен 200, команда не имела никакого эффекта на брандмауэре настройки не были изменены. Почему код python не работает должным образом?

РЕДАКТИРОВАТЬ: я обнаружил, что строка XML полностью игнорируется при запуске кода выше python. Может быть, этот рабочий код в PHP может пролить немного света?

<code><?php

$xml = '<?xml version="1.0" encoding="UTF-8"?>
<Request>
    <Login>
        <Username>admin</Username>
        <Password>admin</Password>
    </Login>
    <Set>
    …
    </Set>
</Request>';
$url = "https://192.1.1.1:90/APIController";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, "reqxml=" . $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
echo '<pre>';
echo htmlentities($data);
echo '
'; if (curl_errno ($ ch)) {print curl_error ($ ch); } else {curl_close ($ ch); }?>

Ответы [ 2 ]

0 голосов
/ 26 апреля 2020

Чтобы сделать это просто, вы можете попробовать выполнить команду curl напрямую через python. Сохраните строку xml в файле. xml

import os
os.system('curl -k https://192.1.1.1:90/APIController -F "reqxml=<<path to file.xml>"')

(обновлено) ИЛИ

На основе вывода команды curl, а также кода php, оно похоже, что тип контента отправляется как multipart/form-data. Может быть, вы можете попытаться использовать тот же Content-type: application/x-www-form-urlencoded с полезной нагрузкой, преобразованной в "reqxml=" + "base64 encoded xml data"

0 голосов
/ 26 апреля 2020

Лучше всего сравнить данные, отправленные по сети, с помощью инструмента / приложения, которые изменяют фактические настройки, и сравнить с вашим запросом python запросов. Если ваш удаленный хост принимает простой HTTP, используйте это и запустите wireshark / tcpdump

--- edit

  1. Попробуйте опубликовать содержимое в виде файла, используя библиотеку запросов.

xml_content = '''<?xml version="1.0" encoding="UTF-8"?>
<Request>
    <Login>
        <Username>admin</Username>
        <Password>admin</Password>
    </Login>
    <Set>
    …
    </Set>
</Request>
'''
url = "https://192.1.1.1:90/APIController"

files = {'file': ('reqxml', xml_content)}
r = requests.post(url, files=files)
...