usarise/turnstile

PHP库用于turnstile,是Cloudflare的智能CAPTCHA替代品。它可以嵌入到任何网站中,无需通过Cloudflare发送流量,且不会向访客显示CAPTCHA。

v0.5.3 2024-07-15 20:47 UTC

This package is auto-updated.

Last update: 2024-08-28 05:15:35 UTC


README

PHP Version Latest Version License Total Downloads GitHub CI

灵感来源于 recaptcha

目录

  1. 安装
  2. 入门
  3. 用法

安装

composer require usarise/turnstile

入门

安装symfony http客户端和nyholm psr7和usarise turnstile

composer require symfony/http-client nyholm/psr7 usarise/turnstile

TurnstileExample.php

<?php

declare(strict_types=1);

require_once __DIR__ . '/vendor/autoload.php';

use Symfony\Component\HttpClient\Psr18Client;
use Turnstile\Error\Code;
use Turnstile\Turnstile;

// Get real API keys at https://dash.cloudflare.com/?to=/:account/turnstile
$siteKey = '1x00000000000000000000AA'; // Always passes (Dummy Testing)
$secretKey = '1x0000000000000000000000000000000AA'; // Always passes (Dummy Testing)

if ($token = $_POST['cf-turnstile-response'] ?? null) {
    $turnstile = new Turnstile(
        client: new Psr18Client(),
        secretKey: $secretKey,
    );

    $response = $turnstile->verify(
        $token, // The response provided by the Turnstile client-side render on your site.
        $_SERVER['REMOTE_ADDR'], // With usage CloudFlare: $_SERVER['HTTP_CF_CONNECTING_IP']
    );

    if ($response->success) {
        echo 'Success!';
    } else {
        $errors = $response->errorCodes;
        var_dump($errors);
        var_dump(Code::toDescription($errors));
    }

    exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Turnstile example</title>
  <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
<form action="" method="POST">
  <!-- The following line controls and configures the Turnstile widget. -->
  <div class="cf-turnstile" data-sitekey="<?php echo $siteKey; ?>" data-theme="light"></div>
  <!-- end. -->
  <button type="submit" value="Submit">Verify</button>
</form>
</body>
</html>

将响应转换为字符串

var_dump((string) $response);

将响应转换为数组

var_dump($response->toArray());

将响应对象转换为数组

var_dump($response->toArray(strict: true));

使用 Turnstile

构造

use Turnstile\Client\Client;
use Turnstile\Turnstile;

$turnstile = new Turnstile(
    client: new Client(...),
    secretKey: 'secret key',
    idempotencyKey: 'idempotency key',
);

简化构造

PSR-18客户端如 php-http/discovery

$turnstile = new Turnstile(
    client: new Psr18Client(),
    secretKey: 'secret key',
    idempotencyKey: 'idempotency key',
);

使用 Client

构造

use Turnstile\Client\Client;
use Turnstile\TurnstileInterface;

$client = new Client(
    client: ..., // implementation Psr\Http\Client\ClientInterface
    requestFactory: ..., // implementation Psr\Http\Message\RequestFactoryInterface (default: requestFactory = client)
    streamFactory: ..., // implementation Psr\Http\Message\StreamFactoryInterface (default: streamFactory = requestFactory)
    siteVerifyUrl: TurnstileInterface::SITE_VERIFY_URL, // https://challenges.cloudflare.com/turnstile/v0/siteverify (default)
);

示例http客户端

Guzzle http客户端

安装
composer require guzzlehttp/guzzle
用法
use GuzzleHttp\Client as GuzzleHttpClient;
use GuzzleHttp\Psr7\HttpFactory;
use Turnstile\Client\Client;

$client = new Client(
    new GuzzleHttpClient(),
    new HttpFactory(),
);

Symfony http客户端和Nyholm PSR-7

安装symfony http客户端和nyholm psr7
composer require symfony/http-client nyholm/psr7
用法
use Symfony\Component\HttpClient\Psr18Client;
use Turnstile\Client\Client;

$client = new Client(
    new Psr18Client(),
);
简化构造
use Symfony\Component\HttpClient\Psr18Client;

$client = new Psr18Client();

Symfony http客户端和Guzzle PSR-7

安装symfony http客户端和guzzlehttp psr7
composer require symfony/http-client guzzlehttp/psr7
用法
use GuzzleHttp\Psr7\HttpFactory;
use Symfony\Component\HttpClient\Psr18Client;
use Turnstile\Client\Client;

$client = new Client(
    new Psr18Client(
        responseFactory: new HttpFactory(),
    ),
);
简化构造
use GuzzleHttp\Psr7\HttpFactory;
use Symfony\Component\HttpClient\Psr18Client;

$client = new Psr18Client(
    responseFactory: new HttpFactory(),
);

Symfony http客户端和Guzzle PSR-7和Discovery

安装symfony http客户端和guzzlehttp psr7和php http discovery
composer require symfony/http-client guzzlehttp/psr7 php-http/discovery
用法
use Symfony\Component\HttpClient\Psr18Client;
use Turnstile\Client\Client;

$client = new Client(
    new Psr18Client(),
);
简化构造
use Symfony\Component\HttpClient\Psr18Client;

$client = new Psr18Client();

Curl http客户端和Nyholm PSR-7

安装nyholm psr7和php http curl客户端
composer require nyholm/psr7 php-http/curl-client
用法
use Http\Client\Curl\Client as CurlClient;
use Nyholm\Psr7\Factory\Psr17Factory;
use Turnstile\Client\Client;

$psr17Factory = new Psr17Factory();

$client = new Client(
    client: new CurlClient(
        responseFactory: $psr17Factory,
        streamFactory: $psr17Factory,
    ),
    requestFactory: $psr17Factory,
);

Discovery http客户端

安装php http discovery
composer require php-http/discovery
用法
use Http\Discovery\Psr18Client;
use Turnstile\Client\Client;

$client = new Client(
    new Psr18Client(),
);
简化构造
use Http\Discovery\Psr18Client;

$client = new Psr18Client();

使用密钥

小部件的密钥。可以在Cloudflare仪表板下的turnstile小部件设置中找到密钥。

真实密钥

API密钥位于 https://dash.cloudflare.com/?to=/:account/turnstile

测试密钥

1x0000000000000000000000000000000AA 总是通过

2x0000000000000000000000000000000AA 总是失败

3x0000000000000000000000000000000AA 返回“token已消耗”错误

示例

use Turnstile\Client\Client;
use Turnstile\Turnstile;

// Real API keys at https://dash.cloudflare.com/?to=/:account/turnstile
$secretKey = '1x0000000000000000000000000000000AA';

$turnstile = new Turnstile(
    client: $client,
    secretKey: $secretKey,
);

使用幂等键

如果应用程序需要重试失败的请求,必须利用幂等功能。

可以通过提供UUID作为idempotencyKey参数,然后使用$turnstile->verify(...)与所需的相同令牌多次调用。

使用Ramsey UUID的示例

安装
composer require ramsey/uuid
用法
use Ramsey\Uuid\Uuid;
use Turnstile\Client\Client;
use Turnstile\Turnstile;

$turnstile = new Turnstile(
    client: $client,
    secretKey: $secretKey, // The site’s secret key.
    idempotencyKey: (string) Uuid::uuid4(), // The UUID to be associated with the response.
);

$response = $turnstile->verify(
    $token, // The response that will be associated with the UUID (idempotencyKey)
);

if ($response->success) {
    // ...
}

$response = $turnstile->verify(
    $token, // The response associated with UUID (idempotencyKey)
);

if ($response->success) {
    // ...
}

使用验证

示例

$response = $turnstile->verify(
    token: $_POST['cf-turnstile-response'], // The response provided by the Turnstile client-side render on your site.
);

远程IP

通过确保当前访客是接收令牌的人来防止滥用,remoteIp参数有助于防止滥用。

目前这尚未严格验证。

基本用法
$response = $turnstile->verify(
    token: $_POST['cf-turnstile-response'], // The response provided by the Turnstile client-side render on your site.
    remoteIp: $_SERVER['REMOTE_ADDR'], // The visitor’s IP address.
);
使用CloudFlare的使用
$response = $turnstile->verify(
    token: $_POST['cf-turnstile-response'], // The response provided by the Turnstile client-side render on your site.
    remoteIp: $_SERVER['HTTP_CF_CONNECTING_IP'], // The visitor’s IP address.
);

扩展

$response = $turnstile->verify(
    ...
    challengeTimeout: 300, // Number of allowed seconds after the challenge was solved.
    expectedHostname: $_SERVER['SERVER_NAME'], // Expected hostname for which the challenge was served.
    expectedAction: 'login', // Expected customer widget identifier passed to the widget on the client side.
    expectedCdata: 'sessionid-123456789', // Expected customer data passed to the widget on the client side.
);

使用响应

成功状态

$response->success

错误代码

$response->errorCodes

挑战时间戳

$response->challengeTs

主机名

$response->hostname

操作

$response->action

客户数据

$response->cdata

转换为字符串

包含原始json数据的字符串

(string) $response

转换为数组

解码的json数据

$response->toArray()

对象转换为数组

基于Response类的属性(successerrorCodeschallengeTshostnameactioncdata)处理的json数据的数组

$response->toArray(strict: true)

使用错误代码到描述

将错误代码转换为适当的语言描述(默认为英文)

use Turnstile\Error\{Code, Description};

var_dump(
    Code::toDescription(
        codes: $response->errorCodes,
        descriptions: Description::TEXTS, // Default
    ),
);