4.2. Распределение доступа и аутентификация¶
4.2.1. Доступ пользователей¶
В теле любого API-запроса используется идентификатор пользователя user_id.
Чтобы посмотреть список идентификаторов, войдите под учетной записью администратора сервера (роль суперадмина) и перейдите на страницу ➝ Панель Администратора ➝ Users.
По API доступ пользователям распределяется по тем же принципам, что и в web-интерфейсе:
Владелец проекта имеет права администратора;
Другие пользователи могут быть добавлены в проект с правами на полное управление или только на просмотр (см. Участники проекта);
Если пользователь не имеет доступа к проекту, тогда для его идентификатора пользователя user_id проект будет также недоступен по API;
При работе по API пользователи с ролями суперадмина и (или) супервайзера (см. Глобальные роли) сохраняют возможности, предусмотренные их ролями.
4.2.2. Подпись API-запросов¶
Аутентификация¶
Для аутентификации пользователя при запросе используется метод цифровой подписи HMAC-SHA2. Используя устойчивые алгоритмы, данный метод довольно прост в реализации на стороне клиента.
Каждый пользователь, который будет управлять сервером через API, получает собственный ключ API. Данный ключ используется в создании цифровой подписи HTTP-запроса. Подпись генерируется на основании набора данных (тела сообщения, даты и др.) и позволяет однозначно аутентифицировать пользователя, от которого осуществляется запрос. Кроме этого, метод позволяет оправлять запросы по незашифрованному протоколу HTTP, т.к. любые модификации тела сообщения приводят к несоответствию оригинальной подписи. Подпись становится недействительной через 1 минуту для защиты от атаки повторного воспроизведения.
Как включить подпись сообщений¶
Войдите под учетной записью администратора сервера Boro VoD (роль суперадмина) и перейдите в настройки
На вкладке Панель администратора ➝ General убедитесь, что в поле
Host nameзадано имя хоста. Без указания Host name не удастся применить настройки API.Перейдите на вкладку Панель администратора ➝ Control API, убедитесь, что чекбокс
Разрешить управление по APIвключен;Здесь же включите чекбокс
Проверять HMAC подписии сохраните настройки;Проверьте настройки доступа к API в Nginx-сервере, т.к. по умолчанию доступ закрыт.
Далее каждый пользователь, который будет управлять сервером, должен сгенерировать свой ключ API. Для этого:
Перейдите в настройки
на вкладку Мой профиль ➝ Control API.
В разделе Control API необходимо нажать кнопку Создать ключ. Данная вкладка активна при условии, что администратора сервера Boro VoD (роль суперадмина) включил опцию
Проверять HMAC подписив 4 пункте выше;Если вы считаете, что ключ API был дискредитирован, можно удалить ключ и сгенерировать новый.
![]()
Полезные ссылки¶
Как это работает¶
Решение по аутентификации пользователей базируется на основе библиотеки ApiAuth, написанной на языке Ruby. Если ваш клиент написан на языке Ruby, вы можете использовать упомянутую библиотеку.
В данном руководстве используется пример кода, написанный на языке Python. Код предназначен для описания базовых принципов генерации подписи. Для создания подписи необходимо выполнить следующие шаги:
Зафиксировать время и дату создания запроса в формате
DAY, DD MON YYYY hh:mm:ss GMTв соответствии с RFC 1123.Важно
Подпись становится недействительной через 1 минуту для защиты от атаки повторного воспроизведения. Необходимо убедиться в синхронизированности времени на сервере Elecard Boro VoD и на компьютере, с которого отправляются запросы на управление по API. В случае несовпадения времени возникнет ошибка верификации подписи. Оптимальным решением является использование NTP-сервера на обоих устройствах.
Вычислить значение заголовка
X-Authorization-Content-SHA256. Это закодированный в Base64 результат хеш-функции SHA-256 от тела HTTP-запроса. В примере кода тело запроса содержится в переменнойrequest_parameters. Приuser_id = '625721355'результат должен быть следующим:x_authorization_content_sha256 = 'OniJqRAkzQHN8KgmAZm/yT5dP94m8CmVVaSTRVg/ptQ='
Сформировать каноническую строку (canonical string). Строка содержит строгую последовательность значений следующих заголовков, разделенных символом запятой:
Request Method,Content-Type,X-Authorization-Content-SHA256,Request URIиDate. Обратите внимание, чтоRequest URIэто не полный URI, а только его часть — путь (Path). Пример канонической строки выглядит следующим образом:canonical_string = 'POST,application/json,OniJqRAkzQHN8KgmAZm/yT5dP94m8CmVVaSTRVg/ptQ=,/ctrl_api/v1/json,Thu, 25 Aug 2022 04:27:52 GMT'
Вычислить код аутентификации сообщения (подпись). Это закодированный в Base64 результат хеш-функции SHA-256 HMAC от канонической строки с использованием ключа API пользователя. Ключ API пользователя предоставляется в формате Base64, поэтому требуется предварительное преобразование ключа в формат Bytes Objects. При
secret_key = 'AGnO/VenzHB9xkLYZG1i70kQ9iyFBBvugGXSFyTQaB0='значение подписи будет следующим:signature = 'vPI9MMRwBZLWNrCcnLnbJjZRna0+XP7yFMhc9KMUFdw='
Добавить подпись в HTTP-запрос. Необходимо убедиться, что все заголовки, которые участвовали в создании канонической строки, передаются в вашем запросе (порядок не учитывается). Обратите внимание, что подпись передается в заголовке
Authorizationв следующем формате:'APIAuth-HMAC-SHA256 ' + user_id + ':' + signature. Пример значения заголовка:authorization_header = 'APIAuth-HMAC-SHA256 625721355:vPI9MMRwBZLWNrCcnLnbJjZRna0+XP7yFMhc9KMUFdw='
Отправить HTTP-запрос.
Как запустить пример кода на Python¶
Для запуска скрипта в вашей системе должен быть установлен Python 3. При попытке запуска система может выдать сообщение об отсутствии необходимых зависимых пакетов. Установите необходимые пакеты, используя пакет pip.
Создайте файл с расширением .py и скопируйте в него содержимое примера кода. В теле скрипта укажите корректные значения полей: адрес сервера
request_host, идентификатор пользователяuser_id, идентификатор проектаproject_id.Откройте командную строку и передайте в виде переменной окружения ваш ключ API:
Windows
set SECRET_ACCESS_KEY=Xf9IXBgd2hdpqqmF3lrwLdmq0tY+nfn+5T39lPEZk5Y=
Linux
export SECRET_ACCESS_KEY=Xf9IXBgd2hdpqqmF3lrwLdmq0tY+nfn+5T39lPEZk5Y=
В этом же окне командной строки перейдите к файлу со скриптом и запустите его:
python api_hmac_signing.py
Результат с успешной верификацией запроса изображен ниже:
Пример кода на Python¶
#!/usr/bin/env python3
# © Copyright 2000-2026 Elecard: Video Compression Guru. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The initial release of this source code was created by Amazon.com, Inc. or its affiliates on 2010-2019.
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Elecard Boro Solution
# API request signing example
# See: https://boro-vod.elecard.com/docs/en/boro-solution-userguide/chapter.ControlAPI/Signing.Requests.html
# This version makes a POST request and passes request parameters
# in the body (payload) of the request. Auth information is passed in
# the Authorization header.
import base64
import hashlib
import hmac
import json
import os
import sys
import requests # pip install requests
# To get a date in RFC 1123 Date Representation
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
# ************* REQUEST VALUES *************
http_method = 'POST'
content_type = 'application/json'
request_host = '172.16.1.41'
request_path = '/ctrl_api/v1/json'
user_id: int = 1
project_id: int = 74
# "AppList" request body passed in a JSON block.
body = {
"user_id": user_id,
"methods": [
{
"method": "AppList",
"params": {
"project_id": project_id,
"app_status": "active"
}
}
]
}
request_parameters = json.dumps(body)
# Best practice is NOT to embed credentials in a code.
# Get API key value from an environment variable
secret_key = os.environ.get('SECRET_ACCESS_KEY')
if secret_key is None:
print('No API key is available.')
sys.exit()
# ************* CREATE THE STRING TO SIGN *************
# Create a date in RFC 1123 Date Representation ('Fri, 05 Aug 2022 03:09:30 GMT') format for headers and the credential string
now = datetime.now()
timestamp = format_date_time(mktime(now.timetuple()))
# Calculate payload (body of the request) hash.
# X-Authorization-Content-SHA256 header is the Base64-encoded SHA-256 hash value used to generate the signature base string.
# This header should be provided by the client, to ensure the request body it sent was not tampered with on its way to the server.
payload_hash = hashlib.sha256(request_parameters.encode('utf-8')).digest()
payload_hash_base64 = base64.b64encode(payload_hash)
x_authorization_content_sha256 = payload_hash_base64.decode('utf-8')
# A canonical string is created using your HTTP headers containing the content-type,
# X-Authorization-Content-SHA256, request path and the date/time stamp.
# This string is then used to create the signature.
canonical_string = http_method + ',' + content_type + ',' + x_authorization_content_sha256 + ',' + request_path + ',' + timestamp
# ************* CALCULATE THE SIGNATURE *************
# Calculate the signature which is a Base64 encoded SHA256 HMAC, using the client's Base64 encoded private API key.
signature_hash = hmac.new(base64.b64decode(secret_key), canonical_string.encode('utf-8'), hashlib.sha256).digest()
signature_hash_base64 = base64.b64encode(signature_hash)
signature = signature_hash_base64.decode('utf-8')
# ************* ADD SIGNING INFORMATION TO THE REQUEST *************
# Put the signature to the Authorization HTTP header in the form: Authorization = APIAuth-HMAC-SHA256 "user_id:signature"
authorization_header = 'APIAuth-HMAC-SHA256 ' + str(user_id) + ':' + signature
# Prepare the necessary headers to be passed in the HTTP request. Order here is not significant.
headers = {'Content-Type': content_type,
'Date': timestamp,
'X-Authorization-Content-SHA256': x_authorization_content_sha256,
'Authorization': authorization_header}
# ************* SEND THE REQUEST *************
request_uri = 'http://' + request_host + request_path
print('\nBEGIN REQUEST:')
print('Request URL = ' + request_uri)
print('Request body = ' + request_parameters)
r = requests.post(request_uri, data=request_parameters, headers=headers)
print('\nRESPONSE:')
print('Response code: %d\n' % r.status_code)
print(r.json())