Deno Fresh용 Cloudflare Turnstile 플러그인(p2)

TL/DR: If you read the title and know exactly what I mean already, simply go to https://deno.land/x/fresh_turnstile and follow the README.



이것은 내 Deno Fresh 플러그인에 대한 시리즈의 2부입니다. 이 게시물에서는 내 Turnstile 플러그인의 첫 번째 릴리스에서 지원하는 나머지 사용 사례에 대해 설명합니다.

사용 사례 2: JavaScript 기반 양식 제출.



이전 게시물에서는 전통적으로 제출된 양식을 보호하는 방법에 대해 논의했습니다. 이제 동일한 양식을 상상하지만 AJAX/fetch/REST APIs/GraphQL 등을 통해 제출됩니다.

암시적 렌더링<CfTurnstile/> 구성 요소를 사용 사례 1과 유사하게 사용할 수 있지만 이번에는 ID와 콜백 속성을 추가합니다.

import { useId, useState } from "preact/hooks";
import CfTurnstile from "$turnstile/components/CfTurnstile.tsx";
// ...
const turnstileElementId = useId();
const [turnstileToken, setTurnstileToken] = useState("");
// ...
<CfTurnstile id={turnstileElementId} sitekey="..." callback={setTurnstileToken} />


콜백을 추가하기만 하면 turnstileToken 상태 변수에서 토큰에 쉽게 액세스할 수 있습니다. 이 상태 변수는 Turnstile 위젯이 액터가 인간이라고 결정하는 즉시 설정됩니다.

그러나 토큰은 최대 한 번만 유효성을 검사할 수 있으므로 서버 측에서 유효성을 검사할 때 어떤 이유로 양식 제출이 실패하면 다른 토큰을 검색할 수 있는 방법이 필요합니다. 이때 아이디가 유용합니다. turnstile 도우미 함수를 사용하여 getTurnstileAsync 개체에 액세스하고 ID로 재설정을 호출합니다.

import { getTurnstileAsync } from "$turnstile/plugin.ts";
// ... imagine this is inside your form submission action
try {
  if (!turnstileToken) {
    throw new Error("Turnstile is not ready");
  }
  await submit_the_form_with_ajax_or_fetch({
    // other form fields
    "cf-turnstile-response": turnstileToken
  });
} catch (e) {
  // form submission fails, get a new Turnstile token to be ready for the next try
  setTurnstileToken("");
  const turnstile = await getTurnstileAsync();
  turnstile.reset(turnstileElementId); 
}


이제 페이지를 다시 로드하거나 다시 렌더링할 필요 없이 다음 제출을 위한 양식이 준비되었습니다.

사용 사례 3: 사용자 지정 상호 작용.



지금쯤이면 이미 이 작업을 수행하는 방법에 대해 상당히 좋은 아이디어를 가지고 있어야 하지만 완전성을 위해 오해가 없도록 서면으로 작성해 둡시다.

이전 사례와 마찬가지로 ID와 콜백이 있는 구성 요소를 사용합니다. 직접 작성한 사전 구성 요소만큼 자유롭게 구성 요소를 사용할 수 있다는 아이디어를 보여주기 위해 이 예제에서는 상태 변수 대신 신호를 사용하겠습니다.

import { useId } from "preact/hooks";
import { useSignal } from "@preact/signals";
import CfTurnstile from "$turnstile/components/CfTurnstile.tsx";
// ...
const turnstileElementId = useId();
const turnstileToken = useSignal("");
// ...
<CfTurnstile id={turnstileElementId} sitekey="..." callback={(token) => turnstileToken.value = token} />


그리고 다시 신호를 검사하고 getTurnstileAsync를 사용하여 필요에 따라 위젯을 재설정할 수 있습니다.

import { getTurnstileAsync } from "$turnstile/plugin.ts";
// ... imagine this is inside your custom interaction
try {
  if (!turnstileToken.value) {
    throw new Error("Turnstile is not ready");
  }
  await validate_token_on_server_side({
    "token": turnstileToken.value}
  );
} catch (e) {
  // validation fails, get a new Turnstile token to be ready for the next try
  turnstileToken.value = "";
  const turnstile = await getTurnstileAsync();
  turnstile.reset(turnstileElementId); 
}


토큰의 유효성을 검사하려면 Turnstile 사이트의 비밀 키를 사용하여 Turnstile API를 호출해야 합니다(공식 지침here 참조). 어느 시점에서든 이 비밀 클라이언트 측을 검색하는 것은 좋은 생각이 아닙니다. 대신 유효성 검사 단계를 수행하기 위해 토큰을 서버 측으로 보내는 것이 좋습니다.

보너스: 명시적 렌더링



Turnstile의 토큰은 비교적 짧은 유효 기간(v0에서 5분)을 갖습니다. 따라서 블로그 게시물, 이메일 또는 기타 시간이 많이 소요되는 양식과 함께 사용하려는 경우 양식 제출 직전에 위젯을 재설정하는 것이 좋습니다.

또는 위젯이 렌더링되는 시기를 제어하고 특성에 따라 시간을 지정하도록 선택할 수 있습니다. 아이디어는 우리가 이전에 수행한 것과 유사합니다: useId 후크 및 getTurnstileAsync 도우미를 활용합니다. 사용자가 양식을 "제출"하기 전에 먼저 "내 양식 확인"버튼을 클릭해야 한다는 점을 제외하면 사용 사례 1과 유사한 매우 간단한 예를 보여드리겠습니다.

import { useId } from "preact/hooks";
import { useSignal, computed } from "@preact/signals";
// ...
const turnstileElementId = useId();
const turnstileToken = useSignal("");
const formReady = computed(() => turnstileToken !== "");
const startTurnstile = async () => {
  const turnstile = await getTurnstileAsync();
  turnstile.render(
    turnstileElementId,
    {
      sitekey: "...",
      callback: (token) => turnstileToken.value = token
    }
  ); 
// ...
<form action="..." method="POST">
  // other form fields such as name, email, message, etc.
  <div id={turnstileElementId} />
  <button type="button" onClick={startTurnstile}>Check my form</button>
  <input type="submit" disabled={!formReady} />
</form>


"check my form"버튼을 클릭하면 위젯 렌더링이 시작됩니다. 액터가 인간이라고 판단되면 turnstileToken 신호로 전송되는 토큰과 함께 콜백을 호출합니다. formReady 신호에 연결되어 "제출"버튼을 비활성화 상태에서 활성화 상태로 바꿉니다. 이제 필요에 따라 동적으로 사용할 토큰이 있습니다. 또한 cf-turnstile-token 안에 <div/>라는 숨겨진 입력이 있어 다른 양식 필드와 함께 제출할 수 있습니다.

이 접근 방식은 매우 유연합니다. 기본 사용 사례가 청구서에 맞지 않는 경우 이 접근 방식으로 대부분의 보안 문자 사용 사례를 해결할 수 있는 창의적인 방법을 찾을 수 있을 것이라고 확신합니다. 풀 수 없는 사용 사례가 있는 경우 share your insight , 또는 prove me wrong 자유롭게 줄을 서십시오. 도전하겠습니다 😉.


그게 다야, 친구들. 끝까지 함께해주셔서 감사합니다. 처음에 말했듯이 이번이 첫 번째 릴리스이므로 다루지 않은 것이 더 많을 것이라고 확신합니다. 부담 없이 start a discussion 또는 file an issue으로 연락주세요! 당신은 또한 dev.to 메시징에서 언제든지 나에게 연락할 수 있습니다!

좋은 웹페이지 즐겨찾기