PowerShell, Get-LiveJournal: «challenge-response» или «cookie»?

Mar 16, 2023 09:21

Окружение: операционная система «Windows 10», программа-оболочка «PowerShell» версии 7, скрипт «Get-LiveJournal».

Для своего скрипта, который общается с ЖЖ («Живым Журналом») по сети по протоколу HTTP(S), я выбирал способ аутентификации из двух вариантов: «challenge-response» или «cookie» (третий возможный способ «clear» не рекомендуется в документации, так как этот способ считается небезопасным). Все эти три способа аутентификации я подробно разобрал в предыдущих постах.

Сам я не проверял, как устроена работа других веб-клиентов, умеющих общаться с ЖЖ, но вот что написал Евгений Ильин в своей статье «Основы работы с сервером livejournal.com» от 2007 года, цитата (пунктуация оригинала сохранена):

Ну что ж, мы рассмотрели с вами три типа авторизации. Каким из них пользоваться решать вам. Скажу только, что Semagic для отправки сообщений использует метод challenge / response, а LJ.NET - cookie.

Из того, что авторы разных веб-клиентов выбирали разные способы аутентификации для реализации в своих веб-клиентах, я делаю вывод о том, что вопрос выбора способа аутентификации заслуживает рассмотрения.

Преимущества и недостатки способа «challenge-response»

Изначально способ аутентификации «challenge-response» выглядит проще способа «cookie» в реализации. При способе «challenge-response» для выполнения задачи с одним HTTP(S)-запросом на запуск какой-либо удалённой функции ЖЖ (кроме «getchallenge», для которой вообще не требуется аутентификации) достаточно выполнить один дополнительный HTTP(S)-запрос для выполнения аутентификации. Для сравнения, при способе аутентификации «cookie» для такой задачи потребуется выполнить три дополнительных HTTP(S)-запроса: один для разовой аутентификации на запуск удалённой функции «sessiongenerate», второй - для запуска функции «sessiongenerate», третий - для запуска функции «sessionexpire» (хотя, можно обойтись и двумя, без выполнения завершения сессии по инициативе веб-клиента).

Однако, для выполнения задачи, для которой требуется выполнение множества HTTP(S)-запросов подряд (например, задача скачивания всех постов журнала, алгоритм которой я разбирал в отдельном посте), способ аутентификации «cookie» в плане эффективности мгновенно обходит способ «challenge-response».

Например, для скачивания журнала с 1000 постов понадобится выполнить 2 HTTP(S)-запроса с запуском удалённой функции «syncitems» и 10 HTTP(S)-запросов с запуском удалённой функции «getevents». При этом при аутентификации способом «challenge-response» понадобится 12 дополнительных HTTP(S)-запросов, а при аутентификации способом «cookie» понадобятся те же 2-3 HTTP(S)-запроса, что и в задаче с одним HTTP(S)-запросом на вызов удалённой функции.

Выбор способа

Какой отсюда следует вывод? Если вам нужно выполнить задачу с одним HTTP(S)-запросом на запуск удалённой функции, то удобнее использовать способ аутентификации «challenge-response». Для выполнения задач со множеством HTTP(S)-запросов эффективнее будет использовать метод аутентификации «cookie». То есть в некоем универсальном веб-клиенте, предназначенном для выполнения разных задач, правильнее всего будет реализовать разные способы аутентификации, которые будут использоваться в зависимости от задачи.

Мой скрипт «Get-LiveJournal» предназначен только для выполнения задачи скачивания всех постов указанного журнала. Эта задача требует выполнения ряда HTTP(S)-запросов подряд, поэтому эффективнее будет использовать аутентификацию способом «cookie» (первый шаг из трех этого способа в моей реализации включает разовую аутентификацию способом «challenge-response»).

Можно ли одно значение «challenge» использовать несколько раз?

Значение «challenge» имеет срок действия в 60 секунд. Но, читая документацию невнимательно, можно пропустить указание о том, что значение «challenge» кроме того, что ограничено сроком действия, еще и является одноразовым.

Цитата из документации, страница про метод аутентификации «challenge-response»:

challenge is an opaque cookie, as generated by the LJ::challenge_generate sub. Challenges may only be used once.

Цитата из документации, страница про удалённую функцию «getchallenge»:

Generate a one-time, quick expiration challenge to be used in challenge/response authentication methods.

Я отметил красным цветом интересные нам места в цитатах.

Если бы значение «challenge» было бы многоразовым, то с помощью аутентификации способом «challenge-response» можно было бы эффективно выполнять аутентификацию для задач со множеством HTTP(S)-запросов (ограничение было бы только в том, сколько можно успеть выполнить HTTP(S)-запросов за 60 секунд). Но это не так.

Я проверил это на практике. Для этого я написал короткий скрипт (для этого скрипта удобно использовать код, приведенный в одном из предыдущих постов), получающий от сервера ЖЖ значение «challenge», а затем пытающийся скачать последний и предпоследний пост указанного журнала двумя отдельными HTTP(S)-запросами на запуск удалённой функции «getevents» со входным параметром «selecttype», равным значению «one» (загрузка только одного поста). При выполнении скачивания двух отдельных постов я применил аутентификацию способом «challenge-response» с помощью одного и того же значения «challenge», полученного в начале.

Один пост у меня загрузился успешно, но при попытке загрузки второго поста в выходном параметре «success» было получено значение «FAIL», а в выходном параметре «errmsg» было получено сообщение «Invalid password». При этом я измерил время работы скрипта с помощью командлета «Get-Date». Продолжительность работы скрипта оказалась равна нескольким секундам. То есть то, что не удалось скачать второй пост, не является следствием истечения срока действия значения «challenge» (который, напомню, равен 60 секундам). Это именно следствие одноразовости значения «challenge».

Инструмент, Образование, Сайтостроение, Программирование, Английский язык, ЖЖ

Previous post Next post
Up