Зміни в документі 2. Налаштування бандла

Остання зміна 2024/07/11 11:49 автором Ashterix

Від версії 3.1
редаговано Ashterix
дата 2024/07/11 11:40
Змінити коментар: Немає коментарів для цієї версії
До версії 2.1
редаговано Ashterix
дата 2024/07/11 09:58
Змінити коментар: Немає коментарів для цієї версії

Підсумок

Подробиці

Властивості сторінки
Назва
... ... @@ -1,1 +1,1 @@
1 -2. Налаштування бандла
1 +tmp
Вміст
... ... @@ -1,377 +1,0 @@
1 -{{box cssClass="floatinginfobox" title="**Зміст**"}}
2 -{{toc/}}
3 -{{/box}}
4 -
5 -{{info}}
6 -Конфігурація зазнала суттєвих змін і не має зворотної сумісності з версією 6.
7 -{{/info}}
8 -
9 -(% class="wikigeneratedid" %)
10 -Всі налаштування бандла знаходяться в файлі {{code language="none"}}config/packages/ufo_json_rpc.yaml{{/code}}.
11 -
12 -(% class="wikigeneratedid" %)
13 -Є можливість налаштувати параметри захисту API та деякі параметри формату даних, що віддається при запиті документації.
14 -
15 -= Блок {{code language="none"}}security{{/code}} =
16 -
17 -Наразі єдиним механізмом захисту доступу до вашого API є встановлення перевірки ключа доступу (api_token).
18 -
19 -== Параметри {{code language="none"}}protected_api{{/code}} та {{code language="none"}}protected_doc{{/code}} (boolean) ==
20 -
21 -(% class="wikigeneratedid" %)
22 -Ці параметри вказує чи мають бути захищені API методи та документація, відповідно.
23 -
24 -(% class="wikigeneratedid" %)
25 -За замовченням апі методи захищені, а документація відкрита.
26 -
27 -{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
28 -ufo_json_rpc:
29 - security:
30 - protected_api: true # Protection API requests
31 - protected_doc: false # Protection API documentation
32 -{{/code}}
33 -
34 -(% id="cke_bm_164641S" style="display:none" %) (%%)Якщо ви захищаєте ваш API через {{code language="none"}}protected_api{{/code}}, вам необхідно налаштувати токени, по яким буде відкритий доступ.
35 -
36 -Перш за все, треба визначитися з назвою токену.
37 -
38 -== Параметр {{code language="none"}}token_name{{/code}} ==
39 -
40 -Компонент {{code language="none"}}RpcSecurity{{/code}} буде шукати в заголовках запиту специфічний ключ, який ви можете встановити в налаштуваннях пакету, значення за замовченням {{code language="none"}}token_name: 'Ufo-RPC-Token'{{/code}}, ви можете встановити будь-яке інше значення яке відповідає наступним вимогам.
41 -
42 -{{spoiler title=" Вимоги до формування заголовків протоколу HTTP"}}
43 -Вимоги до назв заголовків HTTP не є строго регульованими щодо капіталізації, оскільки HTTP заголовки нечутливі до регістру. Однак, існують деякі загальні практики і стандарти, які зазвичай дотримуються для кращої читабельності та узгодженості:
44 -
45 -- Капіталізація: Зазвичай назви HTTP заголовків пишуться з використанням CamelCase, де кожне слово починається з великої літери, наприклад, Content-Type, User-Agent, Accept-Encoding. Це не впливає на технічну обробку заголовків, але робить їх легше читати.
46 -- Унікальність: Кожен заголовок повинен мати унікальну назву у контексті одного HTTP запиту або відповіді. Не можна використовувати однакові назви для різних заголовків у тому самому запиті чи відповіді.
47 -- Спеціальні заголовки: Існують заголовки, які використовуються специфічно для контролю поведінки кешування (Cache-Control), безпеки (Strict-Transport-Security), аутентифікації (Authorization), тощо.
48 -- Норми RFC: Вимоги до заголовків регулюються документами RFC, які визначають стандарти для протоколів Інтернету. Наприклад, загальні заголовки і їхнє використання описані в RFC 7231.
49 -{{/spoiler}}
50 -
51 -
52 -
53 -
54 -
55 -
56 -
57 -
58 -
59 -
60 -
61 -
62 -
63 -
64 -
65 -
66 -
67 -
68 -Параметр {{code language="none"}}clients_tokens{{/code}}
69 -
70 -Тепер слід вказати масив клієнтськіх токенів, які будуть мати доступ до API.
71 -
72 -Тут є певна варіативність.
73 -
74 -=== Токени в параметрах ===
75 -
76 -(% class="box errormessage" %)
77 -(((
78 -**НЕ РЕКОМЕНДОВАНО!!!**
79 -\\Цей підхід допускається лише для локального тестування API
80 -)))
81 -
82 -Є можливість прописати токени хардкодом прямо в файлі налаштувань.
83 -
84 -Це погано з позиції безпеки, якщо код зберігається в публічному репозиторію, то до цього токену буде мати доступ кожен.
85 -
86 -{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
87 -ufo_json_rpc:
88 - security:
89 - token_name: 'Ufo-RPC-Token'
90 - clients_tokens:
91 - - 'ClientTokenExample' # hardcoded token example. Importantly!!! Replace or delete it!
92 -
93 -{{/code}}
94 -
95 -=== Токени в змінних оточення ===
96 -
97 -Це найбільш доцільний механізм у разі, якщо ви розробляєте сервіс для розподіленого бекенду, що написаний на SOA (Сервіс-Орієнтована Архітектура). Зазвичай, в такому випадку, вам треба відкрити доступ до апі одному або обмеженій кількості клієнтських додатків і оновлення ключів не буде відбуватися занадто часто.
98 -
99 -В такому випадку можна прописати токени в змінних оточення (файл {{code language="none"}}.env.local{{/code}} під час локальної розробки). Цей механізм достатньо безпечний з боку збереження доступів.
100 -
101 -(((
102 -{{code language="ini" layout="LINENUMBERS" title=".env.local"}}
103 -TOKEN_FOR_APP_1=9363074966579432364f8b73b3318f71
104 -TOKEN_FOR_APP_2=456fg87g8h98jmnb8675r4445n8up365
105 -{{/code}}
106 -
107 -{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
108 -ufo_json_rpc:
109 - security:
110 - token_key_in_header: 'Ufo-RPC-Token'
111 - clients_tokens:
112 - - '%env(resolve:TOKEN_FOR_APP_1)%' # token example from .env.local
113 - - '%env(resolve:TOKEN_FOR_APP_2)%' # token example from .env.local
114 -{{/code}}
115 -)))
116 -
117 -=== Токени для користувача ===
118 -
119 -Припускаю, що у вас може виникнути потреба зробити персональні ключі для користувачів вашого додатку, можливо ви захочете впровадити ліміти або інші обмеження.
120 -В такому випадку вам не потрібно вказувати перелік токенів в конфігах, ви можете зберігати їх в базі даних або іншому місці згідно вашій бізнес-логіки. Єдина вимога, у вас має бути сервіс, який вміє перевіряти чи існує наданий токен.
121 -
122 -Для того, щоб JsonRpcServer міг використовувати вашу логіку, доведеться реалізувати власний клас, що реалізує інтерфейс {{code language="none"}}Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator{{/code}}
123 -
124 -{{code language="php" layout="LINENUMBERS" title="==== Приклад власного валідатора токенів ===="}}
125 -<?php
126 -
127 -namespace App\Services\RpcSecurity;
128 -
129 -use App\Services\UserService;
130 -use Symfony\Component\Security\Core\Exception\UserNotFoundException;
131 -use Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator;
132 -use Ufo\RpcError\RpcInvalidTokenException;
133 -
134 -class UserTokenValidator implements ITokenValidator
135 -{
136 -
137 - public function __construct(protected UserService $userService) {}
138 -
139 - public function isValid(string $token): true
140 - {
141 - try {
142 - $this->userService->getUserByToken($token);
143 - return true;
144 - } catch (UserNotFoundException $e) {
145 - throw new RpcInvalidTokenException(previous: $e);
146 - }
147 - }
148 -}
149 -{{/code}}
150 -
151 -(% class="box warningmessage" %)
152 -(((
153 -**ВАЖЛИВО!!!**
154 -Метод {{code language="none"}}isValid{{/code}} має повертати {{code language="none"}}true{{/code}} якщо токен існує і валідний, або викидати {{code language="none"}}Ufo\RpcError\RpcInvalidTokenException{{/code}} в іншому разі.
155 -)))
156 -
157 -Після цього вам потрібно в файлі {{code language="none"}}config/services.yaml{{/code}} прописати що класи, що мають залежність від інтерфейса {{code language="none"}}ITokenValidator{{/code}} мають приймати ваш новий клас.
158 -
159 -{{code language="yaml" layout="LINENUMBERS" title="config/services.yaml"}}
160 -parameters:
161 - # some parameters list
162 - # ...
163 -
164 -services:
165 - # some services list
166 - # ...
167 -
168 - Ufo\JsonRpcBundle\Security\Interfaces\ITokenValidator:
169 - class: App\Services\RpcSecurity\UserTokenValidator
170 -{{/code}}
171 -
172 -= Блок {{code language="none"}}async{{/code}} =
173 -
174 -Цей блок для налаштування [[асинхронного транспорту>>doc:docs.JsonRpcBundle.functionality.async.WebHome]].
175 -
176 -Додайте параметр {{code language="none"}}rpc_async{{/code}} який містить рядок у форматі DSN. Цей рядок є конфігурацією [[Symfony Messenger>>https://symfony.com/doc/current/messenger.html]], він вказує на асинхронний транспорт по якому RPC Server буде очікувати вхідні запити якщо у вас запущений консюмер ({{code language="none"}}php bin/console messenger:consume rpc_async{{/code}}). Для більш детального розуміння цього процесу читайте документацію [[Symfony Messenge>>https://symfony.com/doc/current/messenger.html]].
177 -
178 -{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
179 -ufo_json_rpc:
180 - async:
181 - rpc_async: '%env(resolve:RPC_TRANSPORT_DSN)%'
182 -
183 -{{/code}}
184 -
185 -(% class="box warningmessage" %)
186 -(((
187 -Це налаштування має на увазі, що у вас в змінних оточення встановлена змінна RPC_TRANSPORT_DSN що містить DSN рядок.
188 -)))
189 -
190 -= Блок {{code language="none"}}docs{{/code}} =
191 -
192 -Цей блок налаштовує деякі параметри генерації документації коли ви робите GET запит на RPC Server.
193 -
194 -(% class="box infomessage" %)
195 -(((
196 -Починаючи з версії 7, JsonRpcBundle генерує API документацію, що відповідає специфікації [[OpenRpc>>https://spec.open-rpc.org/]]
197 -)))
198 -
199 -* {{code language="none"}}project_name{{/code}}: Назва проєкту, що буде відображена в документації
200 -* {{code language="none"}}project_description{{/code}}: Опис проєкту
201 -* {{code language="none"}}project_version{{/code}}: Поточна версія вашого API
202 -* {{code language="none"}}async_dsn_info{{/code}}: Відповідає за відображення в документації інформації про асинхронний транспорт
203 -* (% id="cke_bm_826282S" style="display:none" %) {{code language="none"}}validations.symfony_asserts{{/code}}(%%): <bool> Відповідає за відображення рядку очікувань валідації для параметра (якщо ви використовуєте [[валідацію>>doc:docs.JsonRpcBundle.add_rpc_service.assertions.WebHome]])
204 -
205 -{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
206 -ufo_json_rpc:
207 - docs:
208 - project_name: 'My Project'
209 - project_description: 'My project description'
210 - project_version: '1.0'
211 - # Optional response details
212 - async_dsn_info: false # Provide information about API that work asynchronously
213 - validations:
214 - symfony_asserts: false # Indicates if an array of Symfony validation constraints is used
215 -
216 -{{/code}}
217 -
218 -==== **Приклад документації ** ====
219 -
220 -{{code language="json" layout="LINENUMBERS" title="GET: /api"}}
221 -{
222 - "envelope": "JSON-RPC-2.0/UFO-RPC-6",
223 - "contentType": "application/json",
224 - "description": "",
225 - "transport": {
226 - "sync": {
227 - "scheme": "http",
228 - "host": "example.com",
229 - "path": "/api",
230 - "method": "POST"
231 - },
232 - "async": {
233 - "scheme": "amqp",
234 - "user": "{user}",
235 - "pass": "{pass}",
236 - "host": "async_rabbit",
237 - "port": 5672,
238 - "path": "/%2f/json-rpc"
239 - }
240 - },
241 - "methods": {
242 - ...
243 - }
244 -}
245 -{{/code}}
246 -
247 -{{info}}
248 -Не переймайтеся щодо безпеки ваших авторизаційних даних. що містяться в DSN.
249 -
250 -Документатор побудований таким чином, що перед виводом інформації про DSN він видаляє дані про користувача і його пароль, а також інші секретні дані, як то токени, секретні ключі, тощо.
251 -
252 -Шаблон, по якому відбувається захист {{code language="none"}}/([\w\d_]*(?:secret|access|token|key)[_\w]*)=((?:\w|\d)+(?=&?))/{{/code}}.
253 -
254 -Приклад:
255 -
256 -{{code language="json" layout="LINENUMBERS" title="RPC_TRANSPORT_DSN=https://sqs.eu-west-3.amazonaws.com/123456789012/messages?access_key=AKIAIOSFODNN7EXAMPLE&secret_key=j17M97ffSVoKI0briFoo9a"}}
257 -{
258 - "async": {
259 - "scheme": "https",
260 - "host": "sqs.eu-west-3.amazonaws.com",
261 - "path": "/123456789012/messages",
262 - "query": "access_key={access_key}&secret_key={secret_key}"
263 - }
264 -}
265 -{{/code}}
266 -{{/info}}
267 -
268 -=== Параметр {{code language="none"}}validations{{/code}} ===
269 -
270 -Відповідає за відображення в документації методів додаткових блоків, що вказують на вимоги до валідації даних.
271 -
272 -Наразі цей блок має два можливих налаштування:
273 -
274 -* {{code language="none"}}json_schema: <bool>{{/code}}
275 -* {{code language="none"}}symfony_asserts: <bool>{{/code}}
276 -
277 -У всіх опцій в цьому параметрі значення за замовченням {{code language="none"}}false{{/code}}, тобто ці блоки не будуть відображатися в документації.
278 -Якщо ви потребуєте якийсь з цих блоків інформації при запиті документації, то встановіть значення в {{code language="none"}}true{{/code}}.
279 -
280 -{{code language="yaml" layout="LINENUMBERS" title="config/packages/ufo_json_rpc.yaml"}}
281 -ufo_json_rpc:
282 - docs:
283 - project_name: 'My Project'
284 - project_description: ''
285 - project_version: null
286 - # Optional response details
287 - async_dsn_info: false # Provide information about API that work asynchronously
288 - validations:
289 - symfony_asserts: false # Indicates if an array of Symfony validation constraints is used
290 -
291 -{{/code}}
292 -
293 -==== **Приклад документації ** ====
294 -
295 -(% class="box infomessage" %)
296 -(((
297 -В цьому прикладі я видалив вміст обʼєктів symfony_assertions для спрощення прикладу.
298 -Детальніше про валідацію методів дивись сторінку **[[Валідація процедур>>doc:docs.JsonRpcBundle.add_rpc_service.assertions.WebHome]]**
299 -)))
300 -
301 -{{code language="json" layout="LINENUMBERS" title="GET: /api"}}
302 -{
303 - "openrpc":"1.2.6",
304 - "info":{
305 - "title":"My Project",
306 - "description":"My project description",
307 - "contact":{
308 - "name":"ufo-tech/json-rpc-bundle",
309 - "url":"https://docs.ufo-tech.space/bin/view/docs/JsonRpcBundle/?language=en"
310 - },
311 - "license":{
312 - "name":"MIT"
313 - },
314 - "version":"1.0"
315 - },
316 - "servers":[
317 - {
318 - "url":"https://mysite.com/api",
319 - "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.",
320 - "name":"UFO Json-RPC Server v.7.0.0",
321 - "x-method":"POST",
322 - "x-ufo":{
323 - "envelop":"JSON-RPC-2.0/UFO-RPC-7.0.0",
324 - "transport":{
325 - "sync":{
326 - "scheme":"https",
327 - "host":"mysite.com",
328 - "path":"/api",
329 - "method":"POST"
330 - },
331 - "async":{
332 - "scheme":"amqp",
333 - "user":"{user}",
334 - "pass":"{pass}",
335 - "host":"mysite.com",
336 - "port":5672,
337 - "path":"/%2f/json-rpc"
338 - }
339 - },
340 - "documentation":{
341 - "json-rpc":"https://www.jsonrpc.org/specification",
342 - "ufo-tech/json-rpc-bundle":"https://docs.ufo-tech.space/bin/view/docs/JsonRpcBundle/?language=en"
343 - }
344 - }
345 - }
346 - ],
347 - "methods":[
348 - {
349 - "name":"getUserNameByUuid",
350 - "tags":[
351 - {
352 - "name":"App\\Api\\UserApiService"
353 - }
354 - ],
355 - "summary":"Get username by id",
356 - "params":[
357 - {
358 - "name":"userId",
359 - "description":"User Id format uuid",
360 - "required":true,
361 - "schema":{
362 - "type":"string"
363 - },
364 - "x-ufo-assertions": "new Assert\\Uuid()"
365 - }
366 - ],
367 - "result":{
368 - "name":"string",
369 - "description":"User Name",
370 - "schema":{
371 - "type":"string"
372 - }
373 - }
374 - }
375 - ]
376 -}
377 -{{/code}}