[{"data":1,"prerenderedAt":1225},["ShallowReactive",2],{"$f0uIxGRqozjSVc8B1lHLLKo0Il7OxhIFnS2yDHkkJ1iM":3,"$fMMUdSFktwQFqMVGPrTtt3EC5yheBp7PzwIqznamFcMo":76,"$fc0LoAJgqXDLbKKd2JS_NpM4SuzBK8EycUXINSg09CKU":79,"$fM3ea55k6lKMPOTM84llDB26VSQDVVbxiQuSBFQw9P_c":84,"$f1Prj1xEczHja_-L7FyIGgRHd5_cSWHo7r6AE5aheAik":429,"$fI5fDmvm-5tr9wcH0eHaKZa1j3y_FQIQaHHPqbZxAHJE":651,"mdc-dhhta9-key":671,"mdc--6dj7tq-key":683,"mdc-5yspwm-key":717,"mdc--cp1kbd-key":726,"mdc--qy34m7-key":735,"mdc-r5yxo8-key":752,"mdc--nz12k6-key":761,"mdc-vh7zkx-key":794,"mdc-10f5yu-key":809,"mdc--otmf3j-key":818,"mdc-9rg84l-key":878,"mdc-wmppiz-key":887,"mdc--pvveou-key":1173,"mdc--62sap2-key":1189},{"content":4,"quizQuestionContent":47,"type":66,"pageMeta":67},[5,9,13,17,20,24,28,31,34,38,41,44],{"id":6,"value":7,"isTypeH1":8},"1910","Как сервер узнаёт авторизацию пользователя на сайте?",true,{"id":10,"value":11,"anchor":12,"isTypeH2":8},"4390","Теория по задаче","theory-on-the-task",{"id":14,"value":15,"anchor":16,"isTypeH3":8},"4398","Суть задачи: HTTP «без состояния»","the-problem-http-is-stateless",{"id":18,"value":19,"isTypeParagraph":8},"10098","HTTP является протоколом без состояния: каждый запрос обрабатывается независимо, поэтому «вход» должен быть привязан к последующим запросам через специальный идентификатор (session id) или токен, который клиент отправляет каждый раз.  \nИдея сводится к тому, что после успешной проверки логина/пароля сервер выдаёт клиенту «доказательство аутентификации», а затем при каждом новом запросе сервер проверяет это доказательство и восстанавливает контекст пользователя.  \n",{"id":21,"description":22,"titleAlert":23,"isTypeAlertInfo":8},"646","После установления аутентифицированной сессии её идентификатор (session ID / token) временно становится эквивалентом «самого сильного» метода аутентификации в приложении, поэтому его утечка равносильна захвату аккаунта.  ",null,{"id":25,"value":26,"anchor":27,"isTypeH3":8},"4399","Варианты хранения состояния","ways-to-carry-auth-state",{"id":29,"value":30,"isTypeParagraph":8},"10099","На практике применяются два основных семейства подходов: «сессионный идентификатор в cookie и состояние на сервере» и «самодостаточный токен (например JWT) и минимум состояния на сервере».  \nВ обоих случаях сервер «узнаёт» пользователя исключительно из того, что пришло в запросе (например, заголовок `Cookie` или `Authorization`), поскольку браузер должен повторно отправлять идентификатор при последующих заходах.  \n\nНиже — компактная схема обмена для cookie-сессии (самый распространённый вариант для сайтов):  \n\n1) POST /login  (credentials)\n2) 200 OK + Set-Cookie: SID=...; Path=/; Secure; HttpOnly\n3) GET /profile  + Cookie: SID=...\n4) Сервер читает SID -> находит сессию -> определяет userId/roles -> авторизует доступ\n",{"id":32,"description":33,"titleAlert":23,"isTypeAlertWarning":8},"706","Передача идентификатора в URL (query-параметрах) повышает риск утечки через историю браузера, логи и заголовок Referer, поэтому предпочтительным механизмом обмена идентификатором считается cookie.  ",{"id":35,"value":36,"anchor":37,"isTypeH3":8},"4400","Правильная реализация: cookie + server-side session","correct-cookie-server-side-session",{"id":39,"value":40,"isTypeParagraph":8},"10100","Сервер после успешного логина генерирует криптографически случайный session id, сохраняет на сервере запись сессии (например, `sid -> userId, expiresAt, roles`) и отправляет `sid` браузеру через `Set-Cookie`, чтобы браузер автоматически возвращал его в `Cookie` на следующих запросах.  \nПо спецификации cookies сервер может отправлять состояние через `Set-Cookie`, а клиент при последующих запросах возвращает его в заголовке `Cookie` в пределах области действия (domain/path) и срока жизни cookie.  \n\nПример HTTP-обмена (ключевой «след» авторизации — cookie `SID`):  \n```\nHTTP/1.1 200 OK\nSet-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly\n\nGET /account HTTP/1.1\nHost: example.com\nCookie: SID=31d4d96e407aad42\n```\n\nДля защиты session id в cookie обычно фиксируются атрибуты, снижающие риск XSS/CSRF/утечки в сети: `Secure` (только HTTPS), `HttpOnly` (недоступно JS API), `SameSite` (ограничение на cross-site отправку cookie).  \n`HttpOnly` ограничивает доступ к cookie из «не-HTTP API» (например, из JavaScript API браузера), что является ключевой мерой против кражи session id через XSS.  \n\nПрактически важные правила жизненного цикла: session id следует регенерировать после смены уровня привилегий (особенно после логина), а при logout/истечении срока — инвалидировать сессию на сервере и очистить cookie на клиенте.  \nТаймауты необходимо обеспечивать на сервере (idle/absolute), поскольку клиентские ограничения времени могут быть подменены атакующим.  \n\nТаблица различий подходов (что именно «говорит» серверу, что пользователь авторизован):  \n\n| Подход | Что приходит в каждом запросе | Где хранится «кто это» | Типичные плюсы | Типичные минусы |\n|---|---|---|---|---|\n| Cookie-сессия (server-side) | `Cookie: SID=...` | В серверном хранилище сессий (Redis/DB/память) | Лёгкая инвалидация (удаление записи), меньше данных на клиенте | Нужна инфраструктура хранения/масштабирования сессий |\n| Bearer token | `Authorization: Bearer \u003Ctoken>` | Обычно токен несёт права/идентичность или ключ к ним | Удобно для API и мобильных клиентов | «Кто владеет токеном — тот и пользователь», требуются меры защиты от утечки |\n| JWT (частный случай токена) | Часто так же `Authorization: Bearer ...` | Часть состояния внутри JWT claims | Меньше запросов к БД на проверку сессии | Нужны строгие сроки (`exp`), сложнее отзыв/инвалидация без доп. механизмов |",{"id":42,"description":43,"titleAlert":23,"isTypeAlertInfo":8},"647","Для JWT критично корректно обрабатывать срок действия: claim `exp` задаёт момент, после которого токен не должен приниматься. ",{"id":45,"value":46,"isTypeParagraph":8},"10101","Кратко: HTTP сам по себе не «помнит» логин; авторизация между запросами поддерживается передачей идентификатора (чаще cookie `SID`) в каждом запросе и проверкой этого идентификатора сервером по серверному хранилищу сессий или по токену (Bearer/JWT) с обязательными мерами защиты (`Secure`, `HttpOnly`, `SameSite`, таймауты, регенерация session id).",{"id":48,"options":49,"hint":63,"solution":64,"description":65},"1149",[50,53,57,60],{"id":51,"label":52,"isCorrect":8},"4741","После логина сервер выставляет cookie с идентификатором сессии через `Set-Cookie`, хранит сопоставление `sid -> user` на сервере и при каждом новом запросе читает `Cookie: sid=...`, чтобы восстановить контекст пользователя и проверить срок/права.  ",{"id":54,"label":55,"isCorrect":56},"4742","После логина сервер «запоминает» пользователя по IP-адресу и User-Agent, а при последующих заходах сравнивает их с прошлым значением; если совпало — пользователь считается авторизованным, даже без cookies и токенов.  ",false,{"id":58,"label":59,"isCorrect":56},"4743","После логина браузер автоматически добавляет логин и пароль в каждый HTTP-запрос, а сервер извлекает их из тела запроса и повторно аутентифицирует пользователя без каких-либо специальных заголовков и без сессий.  ",{"id":61,"label":62,"isCorrect":56},"4744","После логина достаточно сохранить флаг `isLoggedIn=true` в localStorage, потому что браузер будет сам отправлять localStorage на сервер вместе с запросами так же, как он отправляет cookies.  ","Корректный вариант должен объяснять, какой именно артефакт клиент отправляет на каждом запросе (cookie или заголовок), и где хранится соответствие этого артефакта пользователю (на сервере или внутри токена).  ","**Правильный ответ: 1** - После логина сервер выставляет cookie с идентификатором сессии через `Set-Cookie`, хранит сопоставление `sid -> user` на сервере и при каждом новом запросе читает `Cookie: sid=...`, чтобы восстановить контекст пользователя и проверить срок/права.  ","Пользователь авторизован на сайте. Как сервер узнает об этом с последующими другими заходами, что «я – авторизованный пользователь»?","quizQuestion",{"title":7,"description":68,"ogTitle":7,"ogDescription":68,"ogImageUrl":69,"canonical":23,"ogLocale":70,"ogSiteName":71,"ogImageType":72,"ogImageWidth":73,"ogImageHeight":74,"ogType":75,"ogUrl":23},"Теория сессий, cookies, токенов и заголовков: как сохраняется авторизация между запросами и какие риски и настройки важны.","/og-image.png","ru_RU","goodwebjob.ru","image_jpeg","1200","630","article",{"siteName":77,"siteUrl":78},"GOOD WEB JOB!","https://goodwebjob.ru",[80],{"label":81,"slug":82,"to":83},"Подготовка к тех.интервью","technical-interview","/technical-interview/where-to-begin",{"navigationList":85,"navigationSublist":93},[86,89],{"path":83,"isActive":56,"name":87,"icon":88,"isNavbarMobileDisabled":8},"С чего начать?","material-symbols:visibility-outline-rounded",{"path":90,"isActive":8,"name":91,"icon":92,"isNavbarMobileDisabled":56},"/technical-interview/tasks","Сборник задач","material-symbols:task-outline",[94,103,130,142,148,289,313,322,328,390,411,417],{"title":95,"list":96,"isOpened":56},"Bash",[97,100],{"name":98,"path":99,"isActive":56},"Дан фрагмент bash-скрипта: cd ~; mkdir foo... Что в нем происходит?","/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":101,"path":102,"isActive":56},"Дан фрагмент bash-скрипта: target=$(ps -Af | grep $1 | head -n 1)...","/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-target-ps-af-grep-1-head-n-1",{"title":104,"list":105,"isOpened":56},"CSS",[106,109,112,115,118,121,124,127],{"name":107,"path":108,"isActive":56},"Дан HTML-код. Какой будет цвет у текста «Some dummy text»?","/technical-interview/tasks/the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":110,"path":111,"isActive":56},"Есть шаблон HTML и CSS кода. Какой будет цвет у текста «Таким образом, постоянное»?","/technical-interview/tasks/there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":113,"path":114,"isActive":56},"Есть шаблон вложенного HTML кода. Какой будет цвет у текста «One more dummy text»?","/technical-interview/tasks/there-is-a-template-for-embedded-html-code-what-will-be-the-color-of-the-one-more-dummy-text",{"name":116,"path":117,"isActive":56},"Есть шаблон вложенного HTML кода. Будет ли display:block у body влиять на span?","/technical-interview/tasks/there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":119,"path":120,"isActive":56},"Есть HTML код. Будет ли font-weight на span влиять?","/technical-interview/tasks/there-is-an-html-code-will-font-weight-affect-span",{"name":122,"path":123,"isActive":56},"Flexbox и Grid, чем отличаются друг от друга?","/technical-interview/tasks/what-are-the-differences-between-flexbox-and-grid",{"name":125,"path":126,"isActive":56},"Заменяют ли Flexbox и Grid друг друга?","/technical-interview/tasks/do-flexbox-and-grid-replace-each-other",{"name":128,"path":129,"isActive":56},"Есть CSS и JS анимация. Какая между ними разница, что быстрее, что более удобно?","/technical-interview/tasks/there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"title":131,"list":132,"isOpened":56},"Git",[133,136,139],{"name":134,"path":135,"isActive":56},"Разрабатывал, взял закоммитил, запушил. Оказалось, что запушил не в ту ветку, точнее, коммит не в ту ветку. Какие действия?","/technical-interview/tasks/developed-it-committed-it-and-launched-it-it-turned-out-that-i-had-pushed-it-to-the-wrong-branch-or-rather-the-commit-was-in-the-wrong-branch-what-actions",{"name":137,"path":138,"isActive":56},"В git есть несколько вариантов слияния веток, какие? Чем отличаются?","/technical-interview/tasks/git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":140,"path":141,"isActive":56},"Какие существуют стратегии ветвления для работы команды? Что это такое?","/technical-interview/tasks/what-are-the-branching-strategies-for-the-team-what-is-it",{"title":143,"list":144,"isOpened":56},"HTML",[145],{"name":146,"path":147,"isActive":56},"Что такое HTML?","/technical-interview/tasks/what-is-html",{"title":149,"list":150,"isOpened":56},"JavaScript",[151,154,157,160,163,166,169,172,175,178,181,184,187,190,193,196,199,202,205,208,211,214,217,220,223,226,229,232,235,238,241,244,247,250,253,256,259,262,265,268,271,274,277,280,283,286],{"name":152,"path":153,"isActive":56},"Какие логические значения в console.log будут получены?","/technical-interview/tasks/prototype-what-logical-values-will-be-received-in-console-log",{"name":155,"path":156,"isActive":56},"Почему опасно писать прямо в прототипы базовых типов?","/technical-interview/tasks/why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":158,"path":159,"isActive":56},"Что вернёт следующий код? Object.create(null).hasOwnProperty('toString')","/technical-interview/tasks/what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":161,"path":162,"isActive":56},"Какое значение выведет консоль с object.property?","/technical-interview/tasks/what-value-will-the-console-output-with-object-property",{"name":164,"path":165,"isActive":56},"Что выведется в console.log([arr[0](), arr[0]()])?","/technical-interview/tasks/what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":167,"path":168,"isActive":56},"Что выведет console.log в результате выполнения цикла while?","/technical-interview/tasks/what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":170,"path":171,"isActive":56},"Есть функция и объект. Напишите все известные вам способы, чтобы вывести в консоли значение x из объекта, используя функцию","/technical-interview/tasks/there-is-a-function-and-an-object-write-all-the-ways-you-know-to-output-the-value-of-x-from-an-object-in-the-console-using-the-function",{"name":173,"path":174,"isActive":56},"Что вернёт метод book.getUpperName()?","/technical-interview/tasks/what-will-the-book-get-upper-name-method-return",{"name":176,"path":177,"isActive":56},"Переменные объявлены следующим образом: a=3; b=«hello»;. Укажите правильное утверждение","/technical-interview/tasks/variables-are-declared-as-follows-specify-the-correct-statement",{"name":179,"path":180,"isActive":56},"Что выведет консоль в случае присвоения свойства массиву по строковому положительному индексу?","/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":182,"path":183,"isActive":56},"Что выведет консоль в случае присвоения свойства массиву по строковому отрицательному индексу?","/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":185,"path":186,"isActive":56},"Что выведет консоль в случае удаления элемента массива с помощью оператора delete?","/technical-interview/tasks/what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":188,"path":189,"isActive":56},"Что вернёт этот код: typeof (function(){})()","/technical-interview/tasks/what-this-code-will-return-typeof-function",{"name":191,"path":192,"isActive":56},"Что получится в результате передачи объекта как аргумента в функцию и выполнения кода?","/technical-interview/tasks/what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":194,"path":195,"isActive":56},"Какие способы объявления функции есть в JavaScript?","/technical-interview/tasks/what-are-the-ways-to-declare-a-function-in-javascript",{"name":197,"path":198,"isActive":56},"Что такое this в JavaScript?","/technical-interview/tasks/what-is-this-in-javascript",{"name":200,"path":201,"isActive":56},"Что такое Event Loop, как работает?","/technical-interview/tasks/what-is-an-event-loop-and-how-does-it-work",{"name":203,"path":204,"isActive":56},"Что будет, если вызвать typeof на необъявленной переменной?","/technical-interview/tasks/what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":206,"path":207,"isActive":56},"Что показывает оператор typeof в JavaScript?","/technical-interview/tasks/what-does-the-typeof-operator-show-in-javascript",{"name":209,"path":210,"isActive":56},"Какие типы данных существует в JavaScript?","/technical-interview/tasks/what-types-of-data-exist-in-javascript",{"name":212,"path":213,"isActive":56},"Какую структуру использовать для хранения упорядоченного списка строк в JavaScript?","/technical-interview/tasks/what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":215,"path":216,"isActive":56},"Что вернет typeof для массива?","/technical-interview/tasks/what-will-typeof-return-for-an-array",{"name":218,"path":219,"isActive":56},"Почему оператор typeof, применённый к массиву, возвращает объект?","/technical-interview/tasks/why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":221,"path":222,"isActive":56},"Если нужно хранить список уникальных строк, какую структуру данных выбрать?","/technical-interview/tasks/if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":224,"path":225,"isActive":56},"Что возвращает typeof для new Set в JavaScript?","/technical-interview/tasks/what-does-typeof-return-for-new-set-in-javascript",{"name":227,"path":228,"isActive":56},"Почему в JavaScript два объекта с одинаковым содержимым при сравнении возвращают false?","/technical-interview/tasks/why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":230,"path":231,"isActive":56},"В чем разница между микро- и макро-тасками в JavaScript?","/technical-interview/tasks/what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":233,"path":234,"isActive":56},"arr.push(0) повлияет на массив так же, как если бы мы выполнили...","/technical-interview/tasks/arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":236,"path":237,"isActive":56},"Вернуть массив от 1 до n, где числа, кратные 3, заменены на 'fizz', кратные 5 - на 'buzz', а кратные и 3, и 5 одновременно - на 'fizzbuzz'","/technical-interview/tasks/returns-an-array-from-1-to-n-replacing-numbers-that-are-multiples-of-3-with-fizz-numbers-that-are-multiples-of-5-with-buzz-and-numbers-that-are-multiples-of-both-3-and-5-with-fizzbuzz",{"name":239,"path":240,"isActive":56},"Дана строка: 'one.two.three.four.five'. Необходимо из строки сделать вложенный объект","/technical-interview/tasks/the-string-one-two-three-four-five-is-given-it-is-necessary-to-make-a-nested-object-out-of-the-string",{"name":242,"path":243,"isActive":56},"Дано дерево (вложенный объект), надо найти сумму всех вершин","/technical-interview/tasks/given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":245,"path":246,"isActive":56},"Для каждого вложенного объекта нужно добавить свойство level, которое равняется числу - номер вложенности","/technical-interview/tasks/for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":248,"path":249,"isActive":56},"Для каждой ветви дерева записать номер вложенности данной ветви","/technical-interview/tasks/for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":251,"path":252,"isActive":56},"Есть массив, в котором лежат объекты с датами, необходимо отсортировать даты по возрастанию","/technical-interview/tasks/there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":254,"path":255,"isActive":56},"Есть слова в массиве, необходимо определить, состоят ли они из одних и тех же букв","/technical-interview/tasks/there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":257,"path":258,"isActive":56},"Есть строка, состоящая из разных скобок, необходимо проверить, закрыты ли все","/technical-interview/tasks/there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":260,"path":261,"isActive":56}," Найти в массиве неповторяющиеся числа","/technical-interview/tasks/find-non-repeating-numbers-in-an-array",{"name":263,"path":264,"isActive":56},"Напишите функцию, который сделает из массива объект","/technical-interview/tasks/write-a-function-that-will-make-an-object-out-of-an-array",{"name":266,"path":267,"isActive":56},"Необходимо проверить, являются ли две строки анаграммами друг друга","/technical-interview/tasks/checks-whether-two-strings-are-anagrams-of-each-other",{"name":269,"path":270,"isActive":56},"Нечётные числа должны отсортироваться по возрастанию, а чётные должны остаться на своих местах","/technical-interview/tasks/odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":272,"path":273,"isActive":56},"Определить, является ли слово палиндромом","/technical-interview/tasks/determines-whether-a-word-is-a-palindrome",{"name":275,"path":276,"isActive":56},"«Расплющивание» массива","/technical-interview/tasks/flattening-the-array",{"name":278,"path":279,"isActive":56},"Реализовать функцию, принимающую аргументы \"*\", \"1\", \"b\", \"1c\" и возвращающую строку \"1*b*1c\"","/technical-interview/tasks/implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":281,"path":282,"isActive":56},"Сжатие строк","/technical-interview/tasks/string-compression",{"name":284,"path":285,"isActive":56},"Уникализация значений в массиве","/technical-interview/tasks/unifying-values-in-an-array",{"name":287,"path":288,"isActive":56},"Числа от 1 до 100 находятся в массиве, они хаотично перемешанные, но в нём не хватает одного числа из этой последовательности. Необходимо найти его","/technical-interview/tasks/the-numbers-from-1-to-100-are-in-the-array-they-are-randomly-mixed-but-it-lacks-one-number-from-this-sequence-it-is-necessary-to-find-him",{"title":290,"list":291,"isOpened":56},"React",[292,295,298,301,304,307,310],{"name":293,"path":294,"isActive":56},"Для чего нужен React, какие он решает проблемы?","/technical-interview/tasks/what-is-react-used-for-and-what-problems-does-it-solve",{"name":296,"path":297,"isActive":56},"Какой механизм лежит в основе оптимизации обновлений DOM в React?","/technical-interview/tasks/what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":299,"path":300,"isActive":56},"Если убрать в React VDOM/Fiber, и вручную изменять DOM, разве это не оптимально?","/technical-interview/tasks/if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":302,"path":303,"isActive":56},"Есть блок кода. Что в реальном DOM изменится после нажатия на кнопку?","/technical-interview/tasks/there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":305,"path":306,"isActive":56},"Есть код, в котором список и кнопка. Что в реальном DOM изменится после нажатия на кнопку?","/technical-interview/tasks/there-is-a-code-in-which-there-is-a-list-and-a-button-what-will-change-in-the-real-dom-after-clicking-on-the-button",{"name":308,"path":309,"isActive":56},"Зачем нужен Redux (Mobx/Effector)? Зачем нужен менеджер состояния? Какие проблемы решает?","/technical-interview/tasks/why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":311,"path":312,"isActive":56},"Что мешает организовать централизованное состояние без менеджера состояния? Если организовать состояние механизмами реакта: контекстом, стейтом, в чем проблема? Что менеджеры состояния привносят?","/technical-interview/tasks/what-prevents-you-from-organizing-a-centralized-state-without-a-state-manager-if-you-organize-the-state-using-react-context-and-state-mechanisms-what-is-the-problem-what-do-state-managers-add",{"title":314,"list":315,"isOpened":56},"Алгоритмы",[316,319],{"name":317,"path":318,"isActive":56},"Что такое алгоритмическая сложность?","/technical-interview/tasks/what-is-algorithmic-complexity",{"name":320,"path":321,"isActive":56},"Какая алгоритмическая сложность у \"быстрой сортировки\"?","/technical-interview/tasks/what-is-the-algorithmic-complexity-of-quick-sort",{"title":323,"list":324,"isOpened":56},"Дебаггинг",[325],{"name":326,"path":327,"isActive":56},"Как диагностировать и исправить нежелательное изменение цвета фона по клику на кнопку, если исходный код сайта запутан и недоступен для прямого чтения?","/technical-interview/tasks/how-can-diagnose-and-fix-unwanted-background-color-changes-when-clicking-on-a-button-if-the-source-code-of-the-site-is-confusing-and-inaccessible-to-direct-reading",{"title":329,"list":330,"isOpened":56},"Компьютерные сети",[331,334,337,340,343,346,349,352,355,358,361,364,366,369,372,375,378,381,384,387],{"name":332,"path":333,"isActive":56},"Как браузер после ввода домена понимает, откуда брать сайт?","/technical-interview/tasks/how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":335,"path":336,"isActive":56},"Что такое DNS, как DNS находит нужный IP-адрес?","/technical-interview/tasks/what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":338,"path":339,"isActive":56},"Как домен попадает в DNS в таблицу соответствия: домен – ip","/technical-interview/tasks/how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":341,"path":342,"isActive":56},"Как браузер решает, какое соединение ему открывать, TCP или UDP?","/technical-interview/tasks/how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":344,"path":345,"isActive":56},"Ключевые отличия TCP и UDP","/technical-interview/tasks/key-differences-between-tcp-and-udp",{"name":347,"path":348,"isActive":56},"\"TCP/IP\" - кем является TCP, а кем IP в данном случае?","/technical-interview/tasks/tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":350,"path":351,"isActive":56},"Что такое HTTP и из чего состоит?","/technical-interview/tasks/what-is-http-and-what-does-it-consist-of",{"name":353,"path":354,"isActive":56},"Что такое заголовки в HTTP и зачем они нужны?","/technical-interview/tasks/what-are-http-headers-and-why-do-we-need-them",{"name":356,"path":357,"isActive":56},"Что такое параметры в HTTP?","/technical-interview/tasks/what-are-http-parameters",{"name":359,"path":360,"isActive":56},"Где находится HTML-код в структуре HTTP-ответа?","/technical-interview/tasks/where-is-the-html-code-located-in-the-http-response-structure",{"name":362,"path":363,"isActive":56},"Чем отличаются 1.0, 1.1, 2.0, 3.0 версии HTTP?","/technical-interview/tasks/what-are-the-differences-between-http-versions-1-0-1-1-2-0-and-3-0",{"name":65,"path":365,"isActive":56},"/technical-interview/tasks/the-user-is-logged-in-on-the-website-how-does-the-server-know-that-i-am-an-authorized-user-when-the-user-logs-in-again",{"name":367,"path":368,"isActive":56},"Что такое cookie?","/technical-interview/tasks/what-is-a-cookie",{"name":370,"path":371,"isActive":56},"Кто является инициатором записи cookie в браузере?","/technical-interview/tasks/who-initiates-the-cookie-recording-in-the-browser",{"name":373,"path":374,"isActive":56},"Есть ли возможность с клиента (с браузера) управлять cookie?","/technical-interview/tasks/is-it-possible-to-manage-cookies-from-the-client-browser",{"name":376,"path":377,"isActive":56},"Верно ли утверждение, что злоумышленник, контролирующий роутер и прослушивающий трафик, может получить логины и пароли от сайтов, на которые заходит клиент?","/technical-interview/tasks/is-it-true-that-an-attacker-who-controls-a-router-and-listens-to-traffic-can-obtain-logins-and-passwords-from-websites-that-a-client-visits",{"name":379,"path":380,"isActive":56},"Всё, что идет по HTTPS – оно защищено?","/technical-interview/tasks/is-everything-that-goes-through-https-secure",{"name":382,"path":383,"isActive":56},"Все данные зашифрованы, используется https. Хакер взламывает dns и делает подмену одного ip на другой, на фишинговый сайт. В этом случае, злоумышленник может получить данные (логин \\ пароль)?","/technical-interview/tasks/all-data-is-encrypted-https-is-used-let-s-assume-a-hacker-hacks-the-dns-and-makes-a-substitution-of-one-ip-for-another-a-phishing-site",{"name":385,"path":386,"isActive":56},"Есть веб-приложение. Помимо HTTP, какие протоколы того же уровня (Application Layer) можно дополнительно использовать в веб-приложении в браузере?","/technical-interview/tasks/there-is-a-web-application-in-addition-to-http-what-other-protocols-of-the-same-level-application-layer-can-be-used-in-the-web-application-in-browser",{"name":388,"path":389,"isActive":56},"Каким способом может выполняться авторизация пользователя на сайте?","/technical-interview/tasks/how-can-a-user-be-authorized-on-a-website",{"title":391,"list":392,"isOpened":56},"Отрисовка в браузере",[393,396,399,402,405,408],{"name":394,"path":395,"isActive":56},"Что происходит, когда HTTP прислал HTML? Что браузер дальше делает c HTML с учетом того, что она валидная?","/technical-interview/tasks/what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":397,"path":398,"isActive":56},"Как браузер парсит JavaScript и изображения при рендеринге?","/technical-interview/tasks/how-the-browser-parses-javascript-and-images-when-rendering",{"name":400,"path":401,"isActive":56},"Что в браузере блокирует рендеринг страницы?","/technical-interview/tasks/what-is-blocking-the-page-rendering-in-the-browser",{"name":403,"path":404,"isActive":56},"Что такое DOM в браузере? Что такое CSSOM?","/technical-interview/tasks/what-is-dom-in-a-browser-what-is-cssom",{"name":406,"path":407,"isActive":56},"Что является узлами в DOM?","/technical-interview/tasks/what-are-nodes-in-the-dom",{"name":409,"path":410,"isActive":56},"Из чего состоит CSSOM?","/technical-interview/tasks/what-does-cssom-consist-of",{"title":412,"list":413,"isOpened":56},"Ревью кода",[414],{"name":415,"path":416,"isActive":56},"По каким характеристикам, ревьюер понимает, что данный код - хороший, а этот код - плохой?","/technical-interview/tasks/how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"title":418,"list":419,"isOpened":56},"Теория вероятности",[420,423,426],{"name":421,"path":422,"isActive":56},"В комнате три человека. Какова вероятность того, что хотя бы двое из них одного пола? То есть два и более.","/technical-interview/tasks/there-are-three-people-in-the-room-what-is-the-probability-that-at-least-two-of-them-are-of-the-same-sex-that-is-two-or-more",{"name":424,"path":425,"isActive":56},"Есть монета. Ее подбрасывают пять раз подряд. Каждый раз записывается, что выпало - орел или решка. Сколько разных последовательностей орлов и решек может при этом получиться?","/technical-interview/tasks/there-is-a-coin-it-is-tossed-five-times-in-a-row-each-time-it-is-recorded-whether-it-lands-on-heads-or-tails-how-many-different-sequences-of-heads-and-tails-can-be-obtained",{"name":427,"path":428,"isActive":56},"Как гарантированно найти лёгкую фальшивую монету среди 8 за минимальное число взвешиваний на чашечных весах?","/technical-interview/tasks/how-can-you-guarantee-to-find-an-easy-fake-coin-among-8-in-the-minimum-number-of-weighings-on-a-balance-scale",{"slugs":430},[431,434,436,438,440,443,446,448,450,452,454,456,459,461,463,465,467,469,471,473,475,477,479,481,483,485,487,489,491,493,495,497,499,501,503,505,507,509,511,513,515,517,519,521,523,525,527,529,531,533,535,537,540,542,544,546,548,550,552,554,556,558,560,562,564,566,568,570,572,574,576,578,580,582,584,586,588,590,592,594,596,598,600,602,604,606,608,610,612,614,616,618,620,622,624,626,628,630,632,634,636,638,640,641,643,645,647,649],{"name":432,"value":433},"Теоретические задания","theoretical-tasks",{"name":188,"value":435},"what-this-code-will-return-typeof-function",{"name":87,"value":437},"where-to-begin",{"name":155,"value":439},"why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":441,"value":442},"Backend","backend",{"name":444,"value":445},"Frontend","frontend",{"name":152,"value":447},"prototype-what-logical-values-will-be-received-in-console-log",{"name":269,"value":449},"odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":260,"value":451},"find-non-repeating-numbers-in-an-array",{"name":233,"value":453},"arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":239,"value":455},"the-string-one-two-three-four-five-is-given-it-is-necessary-to-make-a-nested-object-out-of-the-string",{"name":457,"value":458},"Реализовать функцию, похоже как в Jquery","implement-a-function-similar-to-jquery",{"name":245,"value":460},"for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":161,"value":462},"what-value-will-the-console-output-with-object-property",{"name":164,"value":464},"what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":236,"value":466},"returns-an-array-from-1-to-n-replacing-numbers-that-are-multiples-of-3-with-fizz-numbers-that-are-multiples-of-5-with-buzz-and-numbers-that-are-multiples-of-both-3-and-5-with-fizzbuzz",{"name":266,"value":468},"checks-whether-two-strings-are-anagrams-of-each-other",{"name":272,"value":470},"determines-whether-a-word-is-a-palindrome",{"name":251,"value":472},"there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":278,"value":474},"implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":242,"value":476},"given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":248,"value":478},"for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":254,"value":480},"there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":287,"value":482},"the-numbers-from-1-to-100-are-in-the-array-they-are-randomly-mixed-but-it-lacks-one-number-from-this-sequence-it-is-necessary-to-find-him",{"name":257,"value":484},"there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":263,"value":486},"write-a-function-that-will-make-an-object-out-of-an-array",{"name":167,"value":488},"what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":170,"value":490},"there-is-a-function-and-an-object-write-all-the-ways-you-know-to-output-the-value-of-x-from-an-object-in-the-console-using-the-function",{"name":182,"value":492},"what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":185,"value":494},"what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":284,"value":496},"unifying-values-in-an-array",{"name":275,"value":498},"flattening-the-array",{"name":173,"value":500},"what-will-the-book-get-upper-name-method-return",{"name":281,"value":502},"string-compression",{"name":179,"value":504},"what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":191,"value":506},"what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":332,"value":508},"how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":338,"value":510},"how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":341,"value":512},"how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":344,"value":514},"key-differences-between-tcp-and-udp",{"name":347,"value":516},"tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":350,"value":518},"what-is-http-and-what-does-it-consist-of",{"name":353,"value":520},"what-are-http-headers-and-why-do-we-need-them",{"name":356,"value":522},"what-are-http-parameters",{"name":359,"value":524},"where-is-the-html-code-located-in-the-http-response-structure",{"name":146,"value":526},"what-is-html",{"name":362,"value":528},"what-are-the-differences-between-http-versions-1-0-1-1-2-0-and-3-0",{"name":65,"value":530},"the-user-is-logged-in-on-the-website-how-does-the-server-know-that-i-am-an-authorized-user-when-the-user-logs-in-again",{"name":367,"value":532},"what-is-a-cookie",{"name":370,"value":534},"who-initiates-the-cookie-recording-in-the-browser",{"name":373,"value":536},"is-it-possible-to-manage-cookies-from-the-client-browser",{"name":538,"value":539},"Лайвкодинг","livecoding",{"name":158,"value":541},"what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":379,"value":543},"is-everything-that-goes-through-https-secure",{"name":382,"value":545},"all-data-is-encrypted-https-is-used-let-s-assume-a-hacker-hacks-the-dns-and-makes-a-substitution-of-one-ip-for-another-a-phishing-site",{"name":385,"value":547},"there-is-a-web-application-in-addition-to-http-what-other-protocols-of-the-same-level-application-layer-can-be-used-in-the-web-application-in-browser",{"name":397,"value":549},"how-the-browser-parses-javascript-and-images-when-rendering",{"name":394,"value":551},"what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":400,"value":553},"what-is-blocking-the-page-rendering-in-the-browser",{"name":403,"value":555},"what-is-dom-in-a-browser-what-is-cssom",{"name":406,"value":557},"what-are-nodes-in-the-dom",{"name":409,"value":559},"what-does-cssom-consist-of",{"name":107,"value":561},"the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":110,"value":563},"there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":113,"value":565},"there-is-a-template-for-embedded-html-code-what-will-be-the-color-of-the-one-more-dummy-text",{"name":116,"value":567},"there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":119,"value":569},"there-is-an-html-code-will-font-weight-affect-span",{"name":122,"value":571},"what-are-the-differences-between-flexbox-and-grid",{"name":125,"value":573},"do-flexbox-and-grid-replace-each-other",{"name":128,"value":575},"there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"name":91,"value":577},"tasks",{"name":194,"value":579},"what-are-the-ways-to-declare-a-function-in-javascript",{"name":197,"value":581},"what-is-this-in-javascript",{"name":200,"value":583},"what-is-an-event-loop-and-how-does-it-work",{"name":203,"value":585},"what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":206,"value":587},"what-does-the-typeof-operator-show-in-javascript",{"name":209,"value":589},"what-types-of-data-exist-in-javascript",{"name":212,"value":591},"what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":215,"value":593},"what-will-typeof-return-for-an-array",{"name":218,"value":595},"why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":221,"value":597},"if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":224,"value":599},"what-does-typeof-return-for-new-set-in-javascript",{"name":293,"value":601},"what-is-react-used-for-and-what-problems-does-it-solve",{"name":299,"value":603},"if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":302,"value":605},"there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":305,"value":607},"there-is-a-code-in-which-there-is-a-list-and-a-button-what-will-change-in-the-real-dom-after-clicking-on-the-button",{"name":308,"value":609},"why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":326,"value":611},"how-can-diagnose-and-fix-unwanted-background-color-changes-when-clicking-on-a-button-if-the-source-code-of-the-site-is-confusing-and-inaccessible-to-direct-reading",{"name":134,"value":613},"developed-it-committed-it-and-launched-it-it-turned-out-that-i-had-pushed-it-to-the-wrong-branch-or-rather-the-commit-was-in-the-wrong-branch-what-actions",{"name":137,"value":615},"git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":140,"value":617},"what-are-the-branching-strategies-for-the-team-what-is-it",{"name":415,"value":619},"how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"name":98,"value":621},"here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":101,"value":623},"here-is-a-fragment-of-a-bash-script-target-ps-af-grep-1-head-n-1",{"name":317,"value":625},"what-is-algorithmic-complexity",{"name":320,"value":627},"what-is-the-algorithmic-complexity-of-quick-sort",{"name":227,"value":629},"why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":388,"value":631},"how-can-a-user-be-authorized-on-a-website",{"name":230,"value":633},"what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":421,"value":635},"there-are-three-people-in-the-room-what-is-the-probability-that-at-least-two-of-them-are-of-the-same-sex-that-is-two-or-more",{"name":424,"value":637},"there-is-a-coin-it-is-tossed-five-times-in-a-row-each-time-it-is-recorded-whether-it-lands-on-heads-or-tails-how-many-different-sequences-of-heads-and-tails-can-be-obtained",{"name":427,"value":639},"how-can-you-guarantee-to-find-an-easy-fake-coin-among-8-in-the-minimum-number-of-weighings-on-a-balance-scale",{"name":81,"value":82},{"name":376,"value":642},"is-it-true-that-an-attacker-who-controls-a-router-and-listens-to-traffic-can-obtain-logins-and-passwords-from-websites-that-a-client-visits",{"name":335,"value":644},"what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":176,"value":646},"variables-are-declared-as-follows-specify-the-correct-statement",{"name":296,"value":648},"what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":311,"value":650},"what-prevents-you-from-organizing-a-centralized-state-without-a-state-manager-if-you-organize-the-state-using-react-context-and-state-mechanisms-what-is-the-problem-what-do-state-managers-add",{"cooperation":652,"copyright":655,"reportError":656,"socialNetwork":658},{"link":653,"title":654},"https://t.me/baurinanton","Сотрудничество","© “GOOD WEB JOB!”",{"label":657,"link":653},"Сообщить об ошибке",{"label":659,"socialNetworkList":660},"Мы в соцсетях:",[661,664,667],{"icon":23,"link":662,"title":663},"https://max.ru/u/f9LHodD0cOKMaukdnnahTeL5pwvjrPfUaZ4S8_1rsNy9I9qsmc9Ar3kP_y8","Max",{"icon":665,"link":653,"title":666},"ic:baseline-telegram","Telegram",{"icon":668,"link":669,"title":670},"ri:vk-fill","https://vk.com/baurinanton","VK",{"data":672,"body":673},{},{"type":674,"children":675},"root",[676],{"type":677,"tag":678,"props":679,"children":680},"element","p",{},[681],{"type":682,"value":65},"text",{"data":684,"body":685},{},{"type":674,"children":686},[687],{"type":677,"tag":678,"props":688,"children":689},{},[690,692,699,701,707,709,715],{"type":682,"value":691},"После логина сервер выставляет cookie с идентификатором сессии через ",{"type":677,"tag":693,"props":694,"children":696},"code",{"className":695},[],[697],{"type":682,"value":698},"Set-Cookie",{"type":682,"value":700},", хранит сопоставление ",{"type":677,"tag":693,"props":702,"children":704},{"className":703},[],[705],{"type":682,"value":706},"sid -> user",{"type":682,"value":708}," на сервере и при каждом новом запросе читает ",{"type":677,"tag":693,"props":710,"children":712},{"className":711},[],[713],{"type":682,"value":714},"Cookie: sid=...",{"type":682,"value":716},", чтобы восстановить контекст пользователя и проверить срок/права.",{"data":718,"body":719},{},{"type":674,"children":720},[721],{"type":677,"tag":678,"props":722,"children":723},{},[724],{"type":682,"value":725},"После логина сервер «запоминает» пользователя по IP-адресу и User-Agent, а при последующих заходах сравнивает их с прошлым значением; если совпало — пользователь считается авторизованным, даже без cookies и токенов.",{"data":727,"body":728},{},{"type":674,"children":729},[730],{"type":677,"tag":678,"props":731,"children":732},{},[733],{"type":682,"value":734},"После логина браузер автоматически добавляет логин и пароль в каждый HTTP-запрос, а сервер извлекает их из тела запроса и повторно аутентифицирует пользователя без каких-либо специальных заголовков и без сессий.",{"data":736,"body":737},{},{"type":674,"children":738},[739],{"type":677,"tag":678,"props":740,"children":741},{},[742,744,750],{"type":682,"value":743},"После логина достаточно сохранить флаг ",{"type":677,"tag":693,"props":745,"children":747},{"className":746},[],[748],{"type":682,"value":749},"isLoggedIn=true",{"type":682,"value":751}," в localStorage, потому что браузер будет сам отправлять localStorage на сервер вместе с запросами так же, как он отправляет cookies.",{"data":753,"body":754},{},{"type":674,"children":755},[756],{"type":677,"tag":678,"props":757,"children":758},{},[759],{"type":682,"value":760},"Корректный вариант должен объяснять, какой именно артефакт клиент отправляет на каждом запросе (cookie или заголовок), и где хранится соответствие этого артефакта пользователю (на сервере или внутри токена).",{"data":762,"body":763},{},{"type":674,"children":764},[765],{"type":677,"tag":678,"props":766,"children":767},{},[768,774,776,781,782,787,788,793],{"type":677,"tag":769,"props":770,"children":771},"strong",{},[772],{"type":682,"value":773},"Правильный ответ: 1",{"type":682,"value":775}," - После логина сервер выставляет cookie с идентификатором сессии через ",{"type":677,"tag":693,"props":777,"children":779},{"className":778},[],[780],{"type":682,"value":698},{"type":682,"value":700},{"type":677,"tag":693,"props":783,"children":785},{"className":784},[],[786],{"type":682,"value":706},{"type":682,"value":708},{"type":677,"tag":693,"props":789,"children":791},{"className":790},[],[792],{"type":682,"value":714},{"type":682,"value":716},{"data":795,"body":796},{},{"type":674,"children":797},[798],{"type":677,"tag":678,"props":799,"children":800},{},[801,803,807],{"type":682,"value":802},"HTTP является протоколом без состояния: каждый запрос обрабатывается независимо, поэтому «вход» должен быть привязан к последующим запросам через специальный идентификатор (session id) или токен, который клиент отправляет каждый раз.",{"type":677,"tag":804,"props":805,"children":806},"br",{},[],{"type":682,"value":808},"\nИдея сводится к тому, что после успешной проверки логина/пароля сервер выдаёт клиенту «доказательство аутентификации», а затем при каждом новом запросе сервер проверяет это доказательство и восстанавливает контекст пользователя.",{"data":810,"body":811},{},{"type":674,"children":812},[813],{"type":677,"tag":678,"props":814,"children":815},{},[816],{"type":682,"value":817},"После установления аутентифицированной сессии её идентификатор (session ID / token) временно становится эквивалентом «самого сильного» метода аутентификации в приложении, поэтому его утечка равносильна захвату аккаунта.",{"data":819,"body":820},{},{"type":674,"children":821},[822,848,853],{"type":677,"tag":678,"props":823,"children":824},{},[825,827,830,832,838,840,846],{"type":682,"value":826},"На практике применяются два основных семейства подходов: «сессионный идентификатор в cookie и состояние на сервере» и «самодостаточный токен (например JWT) и минимум состояния на сервере».",{"type":677,"tag":804,"props":828,"children":829},{},[],{"type":682,"value":831},"\nВ обоих случаях сервер «узнаёт» пользователя исключительно из того, что пришло в запросе (например, заголовок ",{"type":677,"tag":693,"props":833,"children":835},{"className":834},[],[836],{"type":682,"value":837},"Cookie",{"type":682,"value":839}," или ",{"type":677,"tag":693,"props":841,"children":843},{"className":842},[],[844],{"type":682,"value":845},"Authorization",{"type":682,"value":847},"), поскольку браузер должен повторно отправлять идентификатор при последующих заходах.",{"type":677,"tag":678,"props":849,"children":850},{},[851],{"type":682,"value":852},"Ниже — компактная схема обмена для cookie-сессии (самый распространённый вариант для сайтов):",{"type":677,"tag":854,"props":855,"children":856},"ol",{},[857,863,868,873],{"type":677,"tag":858,"props":859,"children":860},"li",{},[861],{"type":682,"value":862},"POST /login  (credentials)",{"type":677,"tag":858,"props":864,"children":865},{},[866],{"type":682,"value":867},"200 OK + Set-Cookie: SID=...; Path=/; Secure; HttpOnly",{"type":677,"tag":858,"props":869,"children":870},{},[871],{"type":682,"value":872},"GET /profile  + Cookie: SID=...",{"type":677,"tag":858,"props":874,"children":875},{},[876],{"type":682,"value":877},"Сервер читает SID -> находит сессию -> определяет userId/roles -> авторизует доступ",{"data":879,"body":880},{},{"type":674,"children":881},[882],{"type":677,"tag":678,"props":883,"children":884},{},[885],{"type":682,"value":886},"Передача идентификатора в URL (query-параметрах) повышает риск утечки через историю браузера, логи и заголовок Referer, поэтому предпочтительным механизмом обмена идентификатором считается cookie.",{"data":888,"body":889},{},{"type":674,"children":890},[891,945,958,970,1009,1019,1024],{"type":677,"tag":678,"props":892,"children":893},{},[894,896,902,904,910,912,917,919,924,926,929,931,936,938,943],{"type":682,"value":895},"Сервер после успешного логина генерирует криптографически случайный session id, сохраняет на сервере запись сессии (например, ",{"type":677,"tag":693,"props":897,"children":899},{"className":898},[],[900],{"type":682,"value":901},"sid -> userId, expiresAt, roles",{"type":682,"value":903},") и отправляет ",{"type":677,"tag":693,"props":905,"children":907},{"className":906},[],[908],{"type":682,"value":909},"sid",{"type":682,"value":911}," браузеру через ",{"type":677,"tag":693,"props":913,"children":915},{"className":914},[],[916],{"type":682,"value":698},{"type":682,"value":918},", чтобы браузер автоматически возвращал его в ",{"type":677,"tag":693,"props":920,"children":922},{"className":921},[],[923],{"type":682,"value":837},{"type":682,"value":925}," на следующих запросах.",{"type":677,"tag":804,"props":927,"children":928},{},[],{"type":682,"value":930},"\nПо спецификации cookies сервер может отправлять состояние через ",{"type":677,"tag":693,"props":932,"children":934},{"className":933},[],[935],{"type":682,"value":698},{"type":682,"value":937},", а клиент при последующих запросах возвращает его в заголовке ",{"type":677,"tag":693,"props":939,"children":941},{"className":940},[],[942],{"type":682,"value":837},{"type":682,"value":944}," в пределах области действия (domain/path) и срока жизни cookie.",{"type":677,"tag":678,"props":946,"children":947},{},[948,950,956],{"type":682,"value":949},"Пример HTTP-обмена (ключевой «след» авторизации — cookie ",{"type":677,"tag":693,"props":951,"children":953},{"className":952},[],[954],{"type":682,"value":955},"SID",{"type":682,"value":957},"):",{"type":677,"tag":959,"props":960,"children":964},"pre",{"className":961,"code":963,"language":682},[962],"language-text","HTTP/1.1 200 OK\nSet-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly\n\nGET /account HTTP/1.1\nHost: example.com\nCookie: SID=31d4d96e407aad42\n",[965],{"type":677,"tag":693,"props":966,"children":968},{"__ignoreMap":967},"",[969],{"type":682,"value":963},{"type":677,"tag":678,"props":971,"children":972},{},[973,975,981,983,989,991,997,999,1002,1007],{"type":682,"value":974},"Для защиты session id в cookie обычно фиксируются атрибуты, снижающие риск XSS/CSRF/утечки в сети: ",{"type":677,"tag":693,"props":976,"children":978},{"className":977},[],[979],{"type":682,"value":980},"Secure",{"type":682,"value":982}," (только HTTPS), ",{"type":677,"tag":693,"props":984,"children":986},{"className":985},[],[987],{"type":682,"value":988},"HttpOnly",{"type":682,"value":990}," (недоступно JS API), ",{"type":677,"tag":693,"props":992,"children":994},{"className":993},[],[995],{"type":682,"value":996},"SameSite",{"type":682,"value":998}," (ограничение на cross-site отправку cookie).",{"type":677,"tag":804,"props":1000,"children":1001},{},[],{"type":677,"tag":693,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":682,"value":988},{"type":682,"value":1008}," ограничивает доступ к cookie из «не-HTTP API» (например, из JavaScript API браузера), что является ключевой мерой против кражи session id через XSS.",{"type":677,"tag":678,"props":1010,"children":1011},{},[1012,1014,1017],{"type":682,"value":1013},"Практически важные правила жизненного цикла: session id следует регенерировать после смены уровня привилегий (особенно после логина), а при logout/истечении срока — инвалидировать сессию на сервере и очистить cookie на клиенте.",{"type":677,"tag":804,"props":1015,"children":1016},{},[],{"type":682,"value":1018},"\nТаймауты необходимо обеспечивать на сервере (idle/absolute), поскольку клиентские ограничения времени могут быть подменены атакующим.",{"type":677,"tag":678,"props":1020,"children":1021},{},[1022],{"type":682,"value":1023},"Таблица различий подходов (что именно «говорит» серверу, что пользователь авторизован):",{"type":677,"tag":1025,"props":1026,"children":1027},"table",{},[1028,1062],{"type":677,"tag":1029,"props":1030,"children":1031},"thead",{},[1032],{"type":677,"tag":1033,"props":1034,"children":1035},"tr",{},[1036,1042,1047,1052,1057],{"type":677,"tag":1037,"props":1038,"children":1039},"th",{},[1040],{"type":682,"value":1041},"Подход",{"type":677,"tag":1037,"props":1043,"children":1044},{},[1045],{"type":682,"value":1046},"Что приходит в каждом запросе",{"type":677,"tag":1037,"props":1048,"children":1049},{},[1050],{"type":682,"value":1051},"Где хранится «кто это»",{"type":677,"tag":1037,"props":1053,"children":1054},{},[1055],{"type":682,"value":1056},"Типичные плюсы",{"type":677,"tag":1037,"props":1058,"children":1059},{},[1060],{"type":682,"value":1061},"Типичные минусы",{"type":677,"tag":1063,"props":1064,"children":1065},"tbody",{},[1066,1099,1131],{"type":677,"tag":1033,"props":1067,"children":1068},{},[1069,1075,1084,1089,1094],{"type":677,"tag":1070,"props":1071,"children":1072},"td",{},[1073],{"type":682,"value":1074},"Cookie-сессия (server-side)",{"type":677,"tag":1070,"props":1076,"children":1077},{},[1078],{"type":677,"tag":693,"props":1079,"children":1081},{"className":1080},[],[1082],{"type":682,"value":1083},"Cookie: SID=...",{"type":677,"tag":1070,"props":1085,"children":1086},{},[1087],{"type":682,"value":1088},"В серверном хранилище сессий (Redis/DB/память)",{"type":677,"tag":1070,"props":1090,"children":1091},{},[1092],{"type":682,"value":1093},"Лёгкая инвалидация (удаление записи), меньше данных на клиенте",{"type":677,"tag":1070,"props":1095,"children":1096},{},[1097],{"type":682,"value":1098},"Нужна инфраструктура хранения/масштабирования сессий",{"type":677,"tag":1033,"props":1100,"children":1101},{},[1102,1107,1116,1121,1126],{"type":677,"tag":1070,"props":1103,"children":1104},{},[1105],{"type":682,"value":1106},"Bearer token",{"type":677,"tag":1070,"props":1108,"children":1109},{},[1110],{"type":677,"tag":693,"props":1111,"children":1113},{"className":1112},[],[1114],{"type":682,"value":1115},"Authorization: Bearer \u003Ctoken>",{"type":677,"tag":1070,"props":1117,"children":1118},{},[1119],{"type":682,"value":1120},"Обычно токен несёт права/идентичность или ключ к ним",{"type":677,"tag":1070,"props":1122,"children":1123},{},[1124],{"type":682,"value":1125},"Удобно для API и мобильных клиентов",{"type":677,"tag":1070,"props":1127,"children":1128},{},[1129],{"type":682,"value":1130},"«Кто владеет токеном — тот и пользователь», требуются меры защиты от утечки",{"type":677,"tag":1033,"props":1132,"children":1133},{},[1134,1139,1150,1155,1160],{"type":677,"tag":1070,"props":1135,"children":1136},{},[1137],{"type":682,"value":1138},"JWT (частный случай токена)",{"type":677,"tag":1070,"props":1140,"children":1141},{},[1142,1144],{"type":682,"value":1143},"Часто так же ",{"type":677,"tag":693,"props":1145,"children":1147},{"className":1146},[],[1148],{"type":682,"value":1149},"Authorization: Bearer ...",{"type":677,"tag":1070,"props":1151,"children":1152},{},[1153],{"type":682,"value":1154},"Часть состояния внутри JWT claims",{"type":677,"tag":1070,"props":1156,"children":1157},{},[1158],{"type":682,"value":1159},"Меньше запросов к БД на проверку сессии",{"type":677,"tag":1070,"props":1161,"children":1162},{},[1163,1165,1171],{"type":682,"value":1164},"Нужны строгие сроки (",{"type":677,"tag":693,"props":1166,"children":1168},{"className":1167},[],[1169],{"type":682,"value":1170},"exp",{"type":682,"value":1172},"), сложнее отзыв/инвалидация без доп. механизмов",{"data":1174,"body":1175},{},{"type":674,"children":1176},[1177],{"type":677,"tag":678,"props":1178,"children":1179},{},[1180,1182,1187],{"type":682,"value":1181},"Для JWT критично корректно обрабатывать срок действия: claim ",{"type":677,"tag":693,"props":1183,"children":1185},{"className":1184},[],[1186],{"type":682,"value":1170},{"type":682,"value":1188}," задаёт момент, после которого токен не должен приниматься.",{"data":1190,"body":1191},{},{"type":674,"children":1192},[1193],{"type":677,"tag":678,"props":1194,"children":1195},{},[1196,1198,1203,1205,1210,1212,1217,1218,1223],{"type":682,"value":1197},"Кратко: HTTP сам по себе не «помнит» логин; авторизация между запросами поддерживается передачей идентификатора (чаще cookie ",{"type":677,"tag":693,"props":1199,"children":1201},{"className":1200},[],[1202],{"type":682,"value":955},{"type":682,"value":1204},") в каждом запросе и проверкой этого идентификатора сервером по серверному хранилищу сессий или по токену (Bearer/JWT) с обязательными мерами защиты (",{"type":677,"tag":693,"props":1206,"children":1208},{"className":1207},[],[1209],{"type":682,"value":980},{"type":682,"value":1211},", ",{"type":677,"tag":693,"props":1213,"children":1215},{"className":1214},[],[1216],{"type":682,"value":988},{"type":682,"value":1211},{"type":677,"tag":693,"props":1219,"children":1221},{"className":1220},[],[1222],{"type":682,"value":996},{"type":682,"value":1224},", таймауты, регенерация session id).",1775735659924]