karser / karser-recaptcha3-bundle
Google ReCAPTCHA v3 for Symfony
Requires
- php: >=7.1
- google/recaptcha: ^1.2
- symfony/expression-language: ^3.4|^4.0|^5.0|^6.0|^7.0
- symfony/form: ^3.4|^4.0|^5.0|^6.0|^7.0
- symfony/framework-bundle: ^3.4.26|^4.2.7|^5.0|^6.0|^7.0
- symfony/twig-bundle: ^3.4|^4.0|^5.0|^6.0|^7.0
- symfony/validator: ^3.4|^4.0|^5.0|^6.0|^7.0
- symfony/yaml: ^3.4|^4.0|^5.0|^6.0|^7.0
- twig/twig: ^2.9|^3.0
Requires (Dev)
- phpunit/phpunit: ^7|^8|^9|^10
- symfony/http-client: ^4.3|^5.0|^6.0|^7.0
- dev-master / 0.1.x-dev
- v0.1.27
- v0.1.26
- v0.1.25
- v0.1.24
- v0.1.23
- v0.1.22
- v0.1.21
- v0.1.20
- v0.1.19
- v0.1.18
- v0.1.17
- v0.1.16
- v0.1.15
- v0.1.14
- v0.1.13
- v0.1.12
- v0.1.11
- v0.1.10
- v0.1.9
- v0.1.8
- v0.1.7
- v0.1.6
- v0.1.5
- v0.1.4
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- dev-fix-phpstan
- dev-sf7
- dev-fix-test
- dev-cve-2019-10909
- dev-validator-alias
- dev-recaptcha-get-score
- dev-php8
- dev-github-actions
This package is auto-updated.
Last update: 2024-09-03 21:18:43 UTC
README
reCAPTCHA v3 在不影响用户体验的情况下为每个请求返回一个分数。该分数基于与您的网站的交互(1.0 表示非常可能是一次良好的交互,0.0 表示非常可能是机器人)并允许您为您的网站采取适当的措施。在此处注册 reCAPTCHA v3 密钥 这里。
安装
使用 composer,需要
composer require karser/karser-recaptcha3-bundle
您可以通过使用 symfony/flex 快速配置此扩展包
不使用 symfony/flex 的配置
1. 注册扩展包
Symfony 4/5/6/7 版本
将扩展包注册到 config/bundles.php
return [ //... Karser\Recaptcha3Bundle\KarserRecaptcha3Bundle::class => ['all' => true], ];
Symfony 3 版本
将扩展包注册到 app/AppKernel.php
public function registerBundles() { return array( // ... new Karser\Recaptcha3Bundle\KarserRecaptcha3Bundle(), ); }
2. 添加配置文件
# config/packages/karser_recaptcha3.yaml (or app/config/config.yml if using Symfony3) karser_recaptcha3: site_key: '%env(RECAPTCHA3_KEY)%' secret_key: '%env(RECAPTCHA3_SECRET)%' score_threshold: 0.5
将您的网站密钥和密钥添加到您的 .env 文件中
###> karser/recaptcha3-bundle ###
RECAPTCHA3_KEY=my_site_key
RECAPTCHA3_SECRET=my_secret
###< karser/recaptcha3-bundle ###
使用
如何在 Symfony 表单中集成 re-captcha
<?php use Karser\Recaptcha3Bundle\Form\Recaptcha3Type; use Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3; class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('captcha', Recaptcha3Type::class, [ 'constraints' => new Recaptcha3(), 'action_name' => 'homepage', 'script_nonce_csp' => $nonceCSP, 'locale' => 'de', ]); } }
注意
action_name
参数是 reCAPTCHA v3 操作,它用于在 Google reCAPTCHA 控制台中识别此特定表单的提交,并在后端进行确认是推荐的额外安全步骤。script_nonce_csp
参数是可选的。您必须使用与您的 Content-Security Policy 标头中相同的 nonce。locale
参数是可选的。它默认为英语,并控制 reCaptcha 小部件的语言。
如何在全球范围内(即使在中国)使用 reCAPTCHA
当 'www.google.com' 不可访问时,在您的代码中使用 'www.recaptcha.net' 主机。
# config/packages/karser_recaptcha3.yaml (or app/config/config.yml if using Symfony3) karser_recaptcha3: host: 'www.recaptcha.net' # default is 'www.google.com'
如何为不同的区域设置 captcha 语言?
您可以通过设置上面的选项中的区域来控制小部件显示的语言。
要更改错误消息,您应安装 Symfony 翻译组件。
然后,将验证文本替换为消息和 messageMissingValue 选项的消息键。
$builder->add('captcha', Recaptcha3Type::class, [ 'constraints' => new Recaptcha3 ([ 'message' => 'karser_recaptcha3.message', 'messageMissingValue' => 'karser_recaptcha3.message_missing_value', ]), ]);
添加英语、西班牙语或任何其他翻译
# translations/validators/validators.en.yaml
karser_recaptcha3.message: 'Your computer or network may be sending automated queries'
karser_recaptcha3.message_missing_value: 'The captcha value is missing'
# translations/validators/validators.es.yaml
karser_recaptcha3.message: 'Es posible que su computadora o red esté enviando consultas automatizadas'
karser_recaptcha3.message_missing_value: 'Falta el valor de captcha'
如何获取 ReCaptcha 分数
在表单提交后注入 Recaptcha3Validator 并调用 getLastResponse()->getScore()
<?php use Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3Validator; class TaskController extends AbstractController { public function new(Request $request, Recaptcha3Validator $recaptcha3Validator): Response { //... $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { //... $score = $recaptcha3Validator->getLastResponse()->getScore(); //... } //... } }
如何将 re-captcha 集成到 API 方法中
思想是要求前端提交 captcha 令牌,因此它将在服务器端进行验证。
首先,您需要将 captcha 字段添加到您的传输实体中
<?php namespace App\Dto; final class UserSignupRequest { /** @var string|null */ public $email; /** @var string|null */ public $captcha; }
然后添加验证约束
#config/validator/validation.yaml App\Dto\UserSignupRequest: properties: email: - NotBlank: ~ - Email: { mode: strict } captcha: - Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3: ~
在前端部分,您需要提交 captcha 令牌以及电子邮件。您可以在页面加载时或表单提交时获取 captcha 令牌。
<script src="https://www.google.com/recaptcha/api.js?render=<siteKey>"></script> <script> const siteKey = '*****************-**-******-******'; //either on page load grecaptcha.ready(function() { grecaptcha.execute(siteKey, { action: 'homepage' }).then(function(token) { //the token will be sent on form submit $('[name="captcha"]').val(token); //keep in mind that token expires in 120 seconds so it's better to add setTimeout. }); }); //or on form post: grecaptcha.ready(function() { grecaptcha.execute(siteKey, { action: 'homepage' }).then(function(token) { //submit the form return http.post(url, {email, captcha: token}); }); }); </script>
如何显示 captcha 响应的错误
只需将 {{ errorCodes }}
变量添加到消息模板中即可
$formBuilder->add('captcha', Recaptcha3Type::class, [
'constraints' => new Recaptcha3(['message' => 'There were problems with your captcha. Please try again or contact with support and provide following code(s): {{ errorCodes }}']),
])
如何处理功能性和端到端测试
Recaptcha不允许你高效地测试你的应用程序,除非你禁用测试环境的Recaptcha。
# app/config/config.yml (or config/packages/karser_recaptcha3.yaml if using Symfony4) karser_recaptcha3: enabled: '%env(bool:RECAPTCHA3_ENABLED)%'
#.env.test or an environment variable
RECAPTCHA3_ENABLED=0
如何从PHP动态设置阈值,而不是从.yaml配置或.env文件中设置?
你应该在你的服务中注入@karser_recaptcha3.google.recaptcha
,并调用setScoreThreshold
方法。
#services.yaml App\Services\YourService: arguments: ['@karser_recaptcha3.google.recaptcha']
#App/Services/YourService.php use ReCaptcha\ReCaptcha; class YourService { private $reCaptcha; public function __construct(ReCaptcha $reCaptcha) { $this->reCaptcha = $reCaptcha; } public function yourMethod() { $this->reCaptcha->setScoreThreshold(0.7); } }
如何在Cloudflare后面正确解析IP地址?
根据Cloudflare文档:为了为每个请求到源站提供客户端(访问者)的IP地址,Cloudflare会添加CF-Connecting-IP头。
"CF-Connecting-IP: A.B.C.D"
因此,你可以实现一个自定义IP解析器,尝试读取CF-Connecting-IP
头,或者在内部IP解析器回退。
<?php declare(strict_types=1); namespace App\Service; use Karser\Recaptcha3Bundle\Services\IpResolverInterface; use Symfony\Component\HttpFoundation\RequestStack; class CloudflareIpResolver implements IpResolverInterface { /** @var IpResolverInterface */ private $decorated; /** @var RequestStack */ private $requestStack; public function __construct(IpResolverInterface $decorated, RequestStack $requestStack) { $this->decorated = $decorated; $this->requestStack = $requestStack; } public function resolveIp(): ?string { return $this->doResolveIp() ?? $this->decorated->resolveIp(); } private function doResolveIp(): ?string { $request = $this->requestStack->getCurrentRequest(); if ($request === null) { return null; } return $request->server->get('HTTP_CF_CONNECTING_IP'); } }
以下是服务声明。它装饰了内部解析器。
#services.yaml services: App\Service\CloudflareIpResolver: decorates: 'karser_recaptcha3.ip_resolver' arguments: $decorated: '@App\Service\CloudflareIpResolver.inner' $requestStack: '@request_stack'
Symfony HttpClient集成
如果你的应用程序依赖于symfony/http-client
,那么它将通过RequestMethod/SymfonyHttpClient
自动连接使用。
故障排除清单
请确保你设置了版本3的recaptcha密钥/密钥。
此外,请确保你已在recaptcha设置中添加了使用的域名。通常开发域与生产域不同,因此最好再次确认。
确保你在渲染的表单的HTML中看到这一点。
<input type="hidden" id="form_captcha" name="form[captcha]" /><script>
var recaptchaCallback_form_captcha = function() {
grecaptcha.execute('<YOUR-RECAPTCHA-KEY>', {action: 'landing'}).then(function(token) {
document.getElementById('form_captcha').value = token;
});
};
</script><script src="https://www.google.com/recaptcha/api.js?render=<YOUR-RECAPTCHA-KEY>&onload=recaptchaCallback_form_captcha" async defer></script>
</form>
确保浏览器控制台中没有JavaScript错误。
测试
composer update
vendor/bin/phpunit