清酒度春秋

给你的网站加上captcha

2025-07-13

前置环境介绍

  1. 安装1panel的服务器

  2. 使用openResty代理的网站

  3. google/cloudflare的账号

nginx增加设置

lua脚本

location ^~ / {
  # 添加 Lua 访问控制
    access_by_lua_block {
        local cookie = ngx.var.http_cookie
        if not cookie or not string.find(cookie, "captcha_verified=true") then
            -- 如果未通过验证,则跳转到验证码页面
            return ngx.redirect("/captcha.html")
        end
    }
# ... 省略
}

静态文件指向captcha.html

location = /captcha.html {
# 注意核对路径
    alias xxxx/captcha.html;
}

captcha.html 代码

1.纯前端方式

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>人机验证</title>
  <style>
    body {
      font-family: sans-serif;
      text-align: center;
      padding-top: 100px;
      background-color: #f9f9f9;
    }
    input[type="text"] {
      padding: 8px;
      font-size: 16px;
      margin-top: 10px;
      width: 200px;
      max-width: 80%;
    }
    button {
      margin-top: 15px;
      padding: 8px 20px;
      font-size: 16px;
      cursor: pointer;
    }
    p {
      font-size: 20px;
      margin-bottom: 20px;
    }
  </style>
</head>
<body>

  <h2>请完成以下验证以继续访问</h2>
  <p id="math-question">计算:3 + 5 = ?</p>
  <input type="text" id="user-answer" placeholder="请输入答案" autofocus />
  <br />
  <button onclick="checkAnswer()">提交</button>

  <script>
    const operators = ['+', '-', '×', '÷'];
    let correctAnswer;

    function generateQuestion() {
      const a = Math.floor(Math.random() * 10) + 1;
      const b = Math.floor(Math.random() * 10) + 1;
      const op = operators[Math.floor(Math.random() * operators.length)];

      let questionText, answer;

      switch(op) {
        case '+': questionText = `计算:${a} + ${b} = ?`; answer = a + b; break;
        case '-': questionText = `计算:${a} - ${b} = ?`; answer = a - b; break;
        case '×': questionText = `计算:${a} × ${b} = ?`; answer = a * b; break;
        case '÷': questionText = `计算:${a * b} ÷ ${b} = ?`; answer = a; break;
      }

      document.getElementById('math-question').innerText = questionText;
      correctAnswer = answer;

      // 自动聚焦输入框
      document.getElementById('user-answer').focus();
    }

    function checkAnswer() {
      const userAnswer = parseInt(document.getElementById('user-answer').value.trim());
      if (userAnswer === correctAnswer) {
        // 验证成功,设置 Cookie 并跳转
        document.cookie = "captcha_verified=true; path=/; max-age=3600";
        window.location.href = "/";
      } else {
        alert("答案错误,请重试");
        generateQuestion(); // 刷新题目
        document.getElementById('user-answer').value = '';
      }
    }

    // 监听回车键提交
    document.getElementById('user-answer').addEventListener('keypress', function(e) {
      if (e.key === 'Enter') {
        checkAnswer();
      }
    });

    // 初始化生成题目
    generateQuestion();
  </script>

</body>
</html>

2.cloudflare方式(本网站用的是这种)

原文档地址 https://developers.cloudflare.com/turnstile/

cloudflare中配置turnstile

选择turnstile页签 添加小组件。主机名配置自己的域名。其他选项默认即可。

创建成功后会生成一个站点密钥 `xxxxxxxxKey`

贴到下面 data-sitekey="key"

上传文件。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>人机验证中...</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <style>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
      padding-top: 100px;
      background-color: #f4f4f4;
    }
    .turnstile-container {
      display: inline-block;
      margin-top: 20px;
    }
  </style>
</head>
<body>

  <h2>请完成人机验证以继续访问</h2>

  <!-- Turnstile 验证组件 -->
  <div class="cf-turnstile" data-sitekey="key" data-callback="onTurnstileSuccess"></div>
  <script src="https://challenges.cloudflare.com/turnstile/v0/api.js " async defer></script>

  <script>
    // 替换为你的目标地址
    const redirectUrl = "/";

    // 全局回调函数:当 Turnstile 成功时调用
    function onTurnstileSuccess(token) {
      if (token) {
        // 设置 Cookie 表示已通过验证(有效期1小时)
        document.cookie = "captcha_verified=true; path=/; max-age=3600";

        // 跳转到主站
        window.location.href = redirectUrl;
      }
    }

    // 确保全局可访问
    window.onTurnstileSuccess = onTurnstileSuccess;
  </script>

</body>
</html>

3.Google recaptcha方式

创建方式与cloudflare大同小异。

以下是v2版recaptcha的代码

贴到 `data-sitekey=`


<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>人机验证中...</title>
    <!-- 引入 reCAPTCHA JS -->
    <script src="https://www.google.com/recaptcha/api.js " async defer></script>

    <script>
        // 当 reCAPTCHA 成功完成时调用
        function onCaptchaSuccess(token) {
            if (token) {
                // 设置 Cookie 表示已通过验证
                document.cookie = "captcha_verified=true; path=/; max-age=3600";

                // 跳转到首页
                window.location.href = "/";
            }
        }

        // 确保全局可访问回调函数
        window.onCaptchaSuccess = onCaptchaSuccess;
    </script>
</head>
<body>
    <h2>请完成人机验证</h2>

    <!-- 标准 reCAPTCHA v2 验证框 -->
    <div class="g-recaptcha"
         data-sitekey="xxxxKey"
         data-callback="onCaptchaSuccess">
    </div>
</body>
</html>