Деджаваскриптизиция (4)
Пора заканчивать эпопею про избавление от Js. Чтобы не утомлять, расскажу о последнем штрихе — как внедрил капчу для комментариев.
Как только я убрал Disqus, полезли спамные комментарии. Каждый день приходят два-три предложения купить виагру, надувную лодку или просто левые ссылки. Поскольку каждый комментарий открывает PR в репозиторий, все остается в истории Гитхаба. Посмотреть на это добро можно по ссылке.
Разгребать подобные комментарии нет желания, поэтому должна быть минимальная защита от спама. С условием — без Js. Надумал такую схему:
- капча генерируется на этапе сборки блога. На выходе получается HTML-форма с полем captcha и значением 2 × 5.
- В форму добавляется поле для решения.
- Сервер парсит капчу, решает и сверяет с ответом. Если что-то не так, заворачивает комментарий.
Как ни странно, даже на таком примитиве боты отваливаются. Разве что с оговоркой: когда был оператор +, боты решали капчу. Как только заменил на ×
(знак умножения в юникоде), стала тишь да благодать. Надеюсь, читатель не забыл таблицу умножения! Тестируя форму, сам подвис с примером 8 × 9
.
Техническая сторона: вот построить капчу в шаблоне:
{% assign val1 = '1 2 3 4 5 6 7 8 9' | split: ' ' | sample %}
{% assign val2 = '1 2 3 4 5 6 7 8 9' | split: ' ' | sample %}
{% assign op = '×' | split: ' ' | sample %}
{% assign captcha = val1 | append: " " | append: op | append: " " | append: val2 %}
Замечу, что при каждой сборке блога значения будут разные.
Скрытое поле в форме:
<input required name="captcha" type="hidden" value="{{ captcha }}">
Виджет для ввода решения:
<div class="block">
<span class="comment-form-label"><small>{{ captcha }} = </small></span>
<input required id="comment-form-solution" name="solution" type="text">
</div>
Наконец, серверный код проверки капчи:
(dеfn validate-captcha [captcha solution]
(when-let [[_ val1-raw op-raw val2-raw]
(re-find #"^(-?\d+) (.+?) (-?\d+)$" captcha)]
(let [val1
(Integer/parseInt val1-raw)
val2
(Integer/parseInt val2-raw)
op
(case op-raw
("+" "+") +
("*" "×" "×") *
nil)]
(when (and val1 val2 op)
(= (str (op val1 val2))
(str/trim solution))))))
Грубо, неуклюже, но работает.
На этом я закончу тему с избавлением от Js. На мой взгляд, цели достигнуты, жить с новыми комментариями можно. Это был интересный опыт, в будущем пригодится.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter
Internet User, 4th Oct 2022, link
Чтож, неплохо!
P.S. диагностировал у себя некоторые проблемы с таблицей умножения
Alex, 5th Oct 2022, link
#Супер комент
Прикольно что можно использовать MD