2. Налаштування бандла
Всі налаштування бандла знаходяться в файлі config/packages/ufo_json_rpc.yaml.
Є можливість налаштувати параметри захисту API та деякі параметри формату даних, що віддається при запиті документації.
Блок security
Наразі єдиним механізмом захисту доступу до вашого API є встановлення перевірки ключа доступу (api_token).
Параметри protected_api та protected_doc (boolean)
Ці параметри вказує чи мають бути захищені API методи та документація, відповідно.
За замовченням апі методи захищені, а документація відкрита.
2
3
4
security:
protected_api: true # Protection API requests
protected_doc: false # Protection API documentation
protected_api, вам необхідно налаштувати токени, по яким буде відкритий доступ.
Якщо ви захищаєте ваш API черезПерш за все, треба визначитися з назвою токену.
Параметр token_name
Компонент RpcSecurity буде шукати в заголовках запиту специфічний ключ, який ви можете встановити в налаштуваннях пакету, значення за замовченням token_name: 'Ufo-RPC-Token', ви можете встановити будь-яке інше значення яке відповідає наступним вимогам.
Вимоги до формування заголовків протоколу HTTP
Параметр clients_tokens
Тепер слід вказати масив клієнтськіх токенів, які будуть мати доступ до API.
Тут є певна варіативність.
Токени в параметрах
Є можливість прописати токени хардкодом прямо в файлі налаштувань.
Це погано з позиції безпеки, якщо код зберігається в публічному репозиторію, то до цього токену буде мати доступ кожен.
2
3
4
5
6
security:
token_name: 'Ufo-RPC-Token'
clients_tokens:
- 'ClientTokenExample' # hardcoded token example. Importantly!!! Replace or delete it!
Токени в змінних оточення
Це найбільш доцільний механізм у разі, якщо ви розробляєте сервіс для розподіленого бекенду, що написаний на SOA (Сервіс-Орієнтована Архітектура). Зазвичай, в такому випадку, вам треба відкрити доступ до апі одному або обмеженій кількості клієнтських додатків і оновлення ключів не буде відбуватися занадто часто.
В такому випадку можна прописати токени в змінних оточення (файл .env.local під час локальної розробки). Цей механізм достатньо безпечний з боку збереження доступів.
2
TOKEN_FOR_APP_2=456fg87g8h98jmnb8675r4445n8up365
2
3
4
5
6
security:
token_key_in_header: 'Ufo-RPC-Token'
clients_tokens:
- '%env(resolve:TOKEN_FOR_APP_1)%' # token example from .env.local
- '%env(resolve:TOKEN_FOR_APP_2)%' # token example from .env.local
Токени для користувача
Припускаю, що у вас може виникнути потреба зробити персональні ключі для користувачів вашого додатку, можливо ви захочете впровадити ліміти або інші обмеження.
В такому випадку вам не потрібно вказувати перелік токенів в конфігах, ви можете зберігати їх в базі даних або іншому місці згідно вашій бізнес-логіки. Єдина вимога, у вас має бути сервіс, який вміє перевіряти чи існує наданий токен.
Для того, щоб JsonRpcServer міг використовувати вашу логіку, доведеться реалізувати власний клас, що реалізує інтерфейс Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator
Приклад власного валідатора токенів
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
namespace App\Services\RpcSecurity;
use App\Services\UserService;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator;
use Ufo\RpcError\RpcInvalidTokenException;
class UserTokenValidator implements ITokenValidator
{
public function __construct(protected UserService $userService) {}
public function isValid(string $token): true
{
try {
$this->userService->getUserByToken($token);
return true;
} catch (UserNotFoundException $e) {
throw new RpcInvalidTokenException(previous: $e);
}
}
}
Після цього вам потрібно в файлі config/services.yaml прописати що класи, що мають залежність від інтерфейса ITokenValidator мають приймати ваш новий клас.
2
3
4
5
6
7
8
9
10
# some parameters list
# ...
services:
# some services list
# ...
Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator:
class: App\Services\RpcSecurity\UserTokenValidator
Блок async
Цей блок для налаштування асинхронного транспорту.
Додайте параметр rpc_async який містить рядок у форматі DSN. Цей рядок є конфігурацією Symfony Messenger, він вказує на асинхронний транспорт по якому RPC Server буде очікувати вхідні запити якщо у вас запущений консюмер (php bin/console messenger:consume rpc_async). Для більш детального розуміння цього процесу читайте документацію Symfony Messenge.
2
3
4
async:
rpc_async: '%env(resolve:RPC_TRANSPORT_DSN)%'
Блок docs
Цей блок налаштовує деякі параметри генерації документації коли ви робите GET запит на RPC Server.
- project_name: Назва проєкту, що буде відображена в документації
- project_description: Опис проєкту
- project_version: Поточна версія вашого API
- async_dsn_info: Відповідає за відображення в документації інформації про асинхронний транспорт
- validations.symfony_asserts: <bool> Відповідає за відображення рядку очікувань валідації для параметра (якщо ви використовуєте валідацію)
2
3
4
5
6
7
8
9
10
docs:
project_name: 'My Project'
project_description: 'My project description'
project_version: '1.0'
# Optional response details
async_dsn_info: false # Provide information about API that work asynchronously
validations:
symfony_asserts: false # Indicates if an array of Symfony validation constraints is used
Приклад документації
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
"openrpc":"1.2.6",
"info":{
"title":"My Project",
"description":"My project description",
"contact":{
"name":"ufo-tech/json-rpc-bundle",
"url":"https://docs.ufo-tech.space/bin/view/docs/JsonRpcBundle/?language=en"
},
"license":{
"name":"MIT"
},
"version":"1.0"
},
"servers":[
{
"url":"https://mysite.com/api",
"description":"Json-RPC api server from UFO Tec\n\nUFO Tech, or Universal Flexible Open Technologies, is an initiative aimed at providing PHP developers with tools to create complex yet user-friendly solutions for modern web applications and service-oriented architectures.",
"name":"UFO Json-RPC Server v.7.0.0",
"x-method":"POST",
"x-ufo":{
"envelop":"JSON-RPC-2.0/UFO-RPC-7.0.0",
"transport":{
"sync":{
"scheme":"https",
"host":"mysite.com",
"path":"/api",
"method":"POST"
},
"async":{
"scheme":"amqp",
"user":"{user}",
"pass":"{pass}",
"host":"mysite.com",
"port":5672,
"path":"/%2f/json-rpc"
}
},
"documentation":{
"json-rpc":"https://www.jsonrpc.org/specification",
"ufo-tech/json-rpc-bundle":"https://docs.ufo-tech.space/bin/view/docs/JsonRpcBundle/?language=en"
}
}
}
],
"methods":[
{
"name":"getUserNameByUuid",
"tags":[
{
"name":"App\\Api\\UserApiService"
}
],
"summary":"Get username by id",
"params":[
{
"name":"userId",
"description":"User Id format uuid",
"required":true,
"schema":{
"type":"string"
},
"x-ufo-assertions": "new Assert\\Uuid()"
}
],
"result":{
"name":"string",
"description":"User Name",
"schema":{
"type":"string"
}
}
}
]
}