Зміни в документі 2. Налаштування бандла
Остання зміна 2024/07/11 11:49 автором Ashterix
Підсумок
-
Властивості сторінки (2 змінено, 0 додано, 0 видалено)
Подробиці
- Властивості сторінки
-
- Назва
-
... ... @@ -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}}