Работа с сессионными куки в Python - PullRequest
0 голосов
/ 27 августа 2018

Я пытаюсь получить доступ к API Kerio Connect (mailserver), который использует jsonrpc в качестве стандарта для своих API.

Существует Session.login метод, который работает просто отлично, я получаю обратно файл SESSION_CONNECT_WEBADMIN, который сохраняется в сеансе:

SESSION_CONNECT_WEBADMIN=2332a56d0203f27972ebbe74c09a7f41262e5b224bc6a05e53e62e5872e9b698; \
path=/admin/; domain=<server>; Secure; HttpOnly; Expires=Tue, 19 Jan 2038 03:14:07 GMT;

Но когда я затем делаю свой следующий запрос с тем же сеансом, я получаю сообщение о том, что мой сеанс истек:

{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32001,
    "message": "Session expired.",
    "data": {
      "messageParameters": {
        "positionalParameters": [],
        "plurality": 1
      }
    }
  }
}

Итак, вот скрипт Python, ведущий к этому сообщению

import json
import requests

userName = "username"
password = "password"

n=1

application = {}
application["name"] = "Log in"
application["vendor"] = "My Company"
application["version"] = "1.0"

params = {}
params["userName"] = userName
params["password"] = password
params["application"] = application

payload = {}
payload["jsonrpc"] = "2.0"
payload["id"] = n
n += 1
payload["method"] = "Session.login"
payload["params"] = params

headers = {}
headers["Content-Type"] = "application/json-rpc"

json_payload =json.dumps(payload, sort_keys=True, indent=2)

url = "https://<server>:4040/admin/api/jsonrpc/"

session = requests.Session()

response = session.post(url, headers=headers, data=json_payload, verify=False)
# Results in a token / a cookie with that token

payload2 = {}
payload2["jsonrpc"] = "2.0"
payload2["id"] = n
n += 1
payload2["method"] = "Users.get"

json_payload2 = json.dumps(payload2, sort_keys=True, indent=2)

response2 = session.post(url, data=json_payload2, verify=False)
print(response2.text)

Что мне здесь не хватает из-за недостатка опыта?

[EDIT]: Я только сейчас понимаю, что когда я вхожу в браузер, на самом деле создаются два куки, каждый с другим токеном, тогда как я получаю обратно только один куки, когда пытаюсь получить доступ к API с помощью Python. Почему это?

  • Файлы cookie, полученные с помощью Chrome:
    • TOKEN_CONNECT_WEBADMIN
    • SESSION_CONNECT_WEBADMIN
  • Cookie, полученный с Python:
    • SESSION_CONNECT_WEBADMIN

1 Ответ

0 голосов
/ 18 января 2019

Рабочий пример:

import json
import urllib.request
import http.cookiejar
import ssl


jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
server = "https://mail.smkh.ru:4040"
username = "admin"
password = "pass"

ssl._create_default_https_context = ssl._create_unverified_context  # disable ssl cert error

def callMethod(method, params, token=None):
    """
    Remotely calls given method with given params.
    :param: method string with fully qualified method name
    :param: params dict with parameters of remotely called method
    :param: token CSRF token is always required except login method. Use method "Session.login" to obtain this token.
    """
    data = {"jsonrpc": "2.0", "id": 1, "method": method, "params": params}

    req = urllib.request.Request(url=server + '/admin/api/jsonrpc/')
    req.add_header('Content-Type', 'application/json')
    if token is not None:
        req.add_header('X-Token', token)

    httpResponse = opener.open(req, json.dumps(data).encode())

    if httpResponse.status == 200:
        body = httpResponse.read().decode()
        return json.loads(body)


session = callMethod("Session.login", {"userName": username, "password": password, "application": {"vendor":"Kerio", "name":"Control Api Demo", "version":"8.4.0"}})
token = session["result"]["token"]

sessions = callMethod("Users.get",
                      {"query": {
                                  "fields": [
                                      "id",
                                      "loginName",
                                      "fullName",
                                      "description",
                                      "authType",
                                      "itemSource",
                                      "isEnabled",
                                      "isPasswordReversible",
                                      "emailAddresses",
                                      "emailForwarding",
                                      "userGroups",
                                      "role",
                                      "itemLimit",
                                      "diskSizeLimit",
                                      "consumedItems",
                                      "consumedSize",
                                      "hasDomainRestriction",
                                      "outMessageLimit",
                                      "effectiveRole",
                                      "homeServer",
                                      "migration",
                                      "lastLoginInfo",
                                      "accessPolicy"
                                  ],
                                  "start": 0,
                                  "limit": 200,
                                  "orderBy": [
                              {
                                  "columnName": "loginName",
                                  "direction": "Asc"
                              }
                          ]
                      },
                       "domainId": Example:"keriodb://domain/908c1118-94ef-49c0-a229-ca672b81d965"
                       },
                      token)
    try:
        user_names = []
        for user in users["result"]["list"]:
            print(user["fullName"], " (", user["loginName"], ")", sep="")
            user_names.append(user["fullName"])
        call_method("Session.logout", {}, token)
        return users

    except KeyError:
        print('Error: {}'.format(users['error']['message']))
        call_method("Session.logout", {}, token)
        return None
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...