История такова: я всегда хотел, чтобы мое резюме было общедоступным для скачивания, а затем я мог разместить его на страницах своего профиля и т. Д., Но я не хочу, чтобы мошенники рассылали спам. Я придумал cgar несколько лет назад, это довольно сложно и требует kubernetes для размещения, я сразу же прекратил его использовать, как только закончился мой бесплатный кредит в Linode. Недавно я снова взялся за поиск работы и воссоздал диспенсер резюме (github), свободно размещенный на CloudFlare.

Шаг 1: Турникет CloudFlare

Я заметил, что OpenAI использует человеческие шашки от CloudFlare, и решил попробовать. Это бесплатно и довольно просто в использовании, и они предоставляют отличные примеры, такие как проверка на стороне сервера (github).

// This is the demo secret key. In production, we recommend
// you store your secret key(s) safely.
const SECRET_KEY = '1x0000000000000000000000000000000AA';

async function handlePost(request) {
 const body = await request.formData();
 // Turnstile injects a token in "cf-turnstile-response".
 const token = body.get('cf-turnstile-response');
 const ip = request.headers.get('CF-Connecting-IP');
 // Validate the token by calling the
 // "/siteverify" API endpoint.
 let formData = new FormData();
 formData.append('secret', SECRET_KEY);
 formData.append('response', token);
 formData.append('remoteip', ip);
 const url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
 const result = await fetch(url, {
  body: formData,
  method: 'POST',
 });
 const outcome = await result.json();
 if (outcome.success) {
  // ...
 }
}

Комментарии

  • Не забудьте добавить домены после развертывания.

Шаг 2: Воркеры CloudFlare

Давайте немного отступим для общей картины с некоторой редукционистской логикой.

  1. Нам нужно разместить файл (резюме) для скачивания. Само по себе это тривиально, мы можем просто выложить на гитхаб.
  2. Нам нужно проверить на человека, это диктует, что мы предоставляем страницу с CAPTCHA. Как только человек проходит захват, мы разрешаем ему загрузку.
  3. Как хост, выполняющий загрузку, как я узнаю, что CAPTCHA прошла успешно? Обычно мы помещаем CAPTCHA на страницу входа в систему, после успешного входа пользователь затем запросит загрузку с подписанным токеном.
  4. Мы являемся общедоступной ссылкой (резюме), вход пользователя в систему невозможен, поэтому мы можем выдавать подписанные токены любому, кто проходит CAPTCHA.

Это приемлемое решение, мы можем реализовать get и post со следующей спецификацией.

  • ПОЛУЧИТЬ: если подписанный токен действителен, вернуть файл. Если токен подписи отсутствует или недействителен, верните форму CAPTCHA.
  • POST: проверьте форму CAPTCHA и верните подписанный токен в виде файла cookie.

Я заметил, что часть токена можно опустить, если мы изменим спецификацию.

  • ПОЛУЧИТЬ: вернуть форму CAPTCHA.
  • POST: проверьте форму CAPTCHA и верните файл.

Я не уверен, нарушает ли какие-либо законы Интернета передача файла по почтовому звонку, но ладно. Моим любимым бесплатным хостингом раньше был netlify, netlify тоже предоставляет воркеры, но с одной смертельной слабостью: хуки воркеров завернуты и могут использовать только JSON в качестве ввода/вывода, то есть невозможно инициировать загрузку в браузере. Я мог бы вернуть содержимое файла в кодировке base64, а затем иметь некоторую логику на стороне клиента для его декодирования (есть множество других трюков, которые мы можем сделать, если зафиксируем полноценный интерфейс), но мои новые любимые рабочие CloudFlare универсальны и экономят мне беда. Он также поставляется с отличным серверным примером для Turnstile (github).

Комментарии по модификации примера (github)

  • wrangler dev отлично, он настраивает локальный сервер для тестирования.
  • Используйте env.TURNSTILE_SECRET для получения секретов в коде.
  • Используйте wrangler secret put TURNSTILE_SECRET, чтобы поместить секреты в CloudFlare.
  • Используйте .dev.vars, чтобы предоставить секреты для локального сервера.
  • "1x0000000000000000000000000000000AA" — это специальный секретный ключ в Turnstile for dev.
  • wrangler publish угадайте, что это делает.
  • Измените HTML-страницу, указав правильный открытый ключ турникета.

Шаг 3: Актив CloudFlare и KV

Мы почти закончили! Теперь структура управления на месте, осталось только подать файл (это CloudFlare, если он что-то делает, то это вещь), я нашел хороший пример (github)

import { getAssetFromKV } from '@cloudflare/kv-asset-handler';
import manifestJSON from '__STATIC_CONTENT_MANIFEST';
const assetManifest = JSON.parse(manifestJSON);

export default {
  async fetch(request, env, ctx) {
    try {
      // Add logic to decide whether to serve an asset or run your original Worker code
      return await getAssetFromKV(
        {
          request,
          waitUntil: ctx.waitUntil.bind(ctx),
        },
        {
          ASSET_NAMESPACE: env.__STATIC_CONTENT,
          ASSET_MANIFEST: assetManifest,
        }
      );
    } catch (e) {
      let pathname = new URL(request.url).pathname;
      return new Response(`"${pathname}" not found`, {
        status: 404,
        statusText: 'not found',
      });
    }
  },
};

Комментарии по модификации примера (github)

  • Поместите активы в папку ./public. Обратите внимание, что я не размещал активы на github, потому что это противоречит цели их защиты с помощью человека-чекера.
  • getAssetFromKV делает всю тяжелую работу за нас, нам просто нужно предоставить ему объект request с URL-адресом, который имеет путь, который сопоставляется с активом. Обратите внимание, что мне пришлось воссоздать объект request с методом GET.
  • Наши активы кэшируются в KV, то есть в базе данных. Это означает, что мы можем зайти в консоль CloudFlare и вручную изменить обслуживаемый файл (до тех пор, пока он не будет переопределен при следующем развертывании).

Оригинал: https://bettercallshao.com/share-resume-with-humans-not-bots/