From bcacdbe8cf6a313e4b7a5e309e508d660540b0c2 Mon Sep 17 00:00:00 2001 From: "Michael H. Arieli" Date: Fri, 8 Apr 2022 10:25:43 -0700 Subject: [PATCH] RE #278, #288: Fixed validator with proxy --- README.md | 24 ++++++++++--------- .../ReCaptcha/RequestMethod/ProxyPost.php | 6 ++++- src/Resources/config/services.yml | 2 +- .../Constraints/IsTrueValidatorV3.php | 10 ++++---- .../Constraints/IsTrueValidatorV3Test.php | 10 +++++--- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 21d6528..f3db8dc 100755 --- a/README.md +++ b/README.md @@ -82,6 +82,19 @@ ewz_recaptcha: api_host: recaptcha.net ``` +You can add HTTP Proxy configuration: + +``` yaml +# app/config/config.yml + +ewz_recaptcha: + // ... + http_proxy: + host: proxy.mycompany.com + port: 3128 + auth: proxy_username:proxy_password +``` + #### v2 only Configuration Sets the default locale: @@ -117,18 +130,7 @@ ewz_recaptcha: // ... ajax: true ``` -You can add HTTP Proxy configuration: - -``` yaml -# app/config/config.yml -ewz_recaptcha: - // ... - http_proxy: - host: proxy.mycompany.com - port: 3128 - auth: proxy_username:proxy_password -``` In case you have turned off the domain name checking on reCAPTCHA's end, you'll need to check the origin of the response by enabling the ``verify_host`` option: ``` yaml diff --git a/src/Extension/ReCaptcha/RequestMethod/ProxyPost.php b/src/Extension/ReCaptcha/RequestMethod/ProxyPost.php index 9c6013a..2017baa 100644 --- a/src/Extension/ReCaptcha/RequestMethod/ProxyPost.php +++ b/src/Extension/ReCaptcha/RequestMethod/ProxyPost.php @@ -63,6 +63,10 @@ public function submit(RequestParameters $params): string return $this->cache[$cacheKey]; } + $proxyAuth = !empty($this->httpProxy['auth']) + ? sprintf('Proxy-Authorization: Basic %s', base64_encode($this->httpProxy['auth'])) + : null; + /** * PHP 5.6.0 changed the way you specify the peer name for SSL context options. * Using "CN_name" will still work, but it will raise deprecated errors. @@ -70,7 +74,7 @@ public function submit(RequestParameters $params): string $peerKey = version_compare(PHP_VERSION, '5.6.0', '<') ? 'CN_name' : 'peer_name'; $options = array( 'http' => array( - 'header' => "Content-type: application/x-www-form-urlencoded\r\n".sprintf('Proxy-Authorization: Basic %s', base64_encode($this->httpProxy['auth'])), + 'header' => sprintf("Content-type: application/x-www-form-urlencoded\r\n%s", $proxyAuth), 'method' => 'POST', 'content' => $params->toQueryString(), // Force the peer to validate (not needed in 5.6.0+, but still works) diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index 911a243..f36bd51 100755 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -70,8 +70,8 @@ services: public: true arguments: - '%ewz_recaptcha.enabled%' - - '%ewz_recaptcha.private_key%' - '%ewz_recaptcha.score_threshold%' + - '@ewz_recaptcha.recaptcha' - '@request_stack' - '@logger' tags: diff --git a/src/Validator/Constraints/IsTrueValidatorV3.php b/src/Validator/Constraints/IsTrueValidatorV3.php index 05f6c78..155c526 100755 --- a/src/Validator/Constraints/IsTrueValidatorV3.php +++ b/src/Validator/Constraints/IsTrueValidatorV3.php @@ -32,21 +32,21 @@ class IsTrueValidatorV3 extends ConstraintValidator * ContainsRecaptchaValidator constructor. * * @param bool $enabled - * @param string $secretKey * @param float $scoreThreshold + * @param ReCaptcha $scoreThreshold * @param RequestStack $requestStack * @param LoggerInterface $logger */ public function __construct( bool $enabled, - string $secretKey, float $scoreThreshold, + ReCaptcha $reCaptcha, RequestStack $requestStack, LoggerInterface $logger ) { $this->enabled = $enabled; - $this->secretKey = $secretKey; $this->scoreThreshold = $scoreThreshold; + $this->reCaptcha = $reCaptcha; $this->requestStack = $requestStack; $this->logger = $logger; } @@ -91,9 +91,7 @@ private function isTokenValid(string $token): bool $remoteIp = $this->requestStack->getCurrentRequest()->getClientIp(); $action = $this->getActionName(); - $recaptcha = new ReCaptcha($this->secretKey); - - $response = $recaptcha + $response = $this->reCaptcha ->setExpectedAction($action) ->setScoreThreshold($this->scoreThreshold) ->verify($token, $remoteIp); diff --git a/tests/Validator/Constraints/IsTrueValidatorV3Test.php b/tests/Validator/Constraints/IsTrueValidatorV3Test.php index b4b8ad3..0582597 100644 --- a/tests/Validator/Constraints/IsTrueValidatorV3Test.php +++ b/tests/Validator/Constraints/IsTrueValidatorV3Test.php @@ -7,6 +7,7 @@ use EWZ\Bundle\RecaptchaBundle\Validator\Constraints\IsTrueValidatorV3; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use ReCaptcha\ReCaptcha; use stdClass; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Validator\Constraint; @@ -18,6 +19,7 @@ class IsTrueValidatorV3Test extends TestCase public function testNotEnabledDoesNotValidate(): void { + $reCaptcha = $this->createMock(ReCaptcha::class); $requestStack = $this->createMock(RequestStack::class); $logger = $this->createMock(LoggerInterface::class); $context = $this->createMock(ExecutionContextInterface::class); @@ -26,13 +28,14 @@ public function testNotEnabledDoesNotValidate(): void $context->expects(self::never()) ->method('buildViolation'); - $validator = new IsTrueValidatorV3(false, 'secret', 0.1, $requestStack, $logger); + $validator = new IsTrueValidatorV3(false, 0.1, $reCaptcha, $requestStack, $logger); $validator->initialize($context); $validator->validate('', $this->createMock(Constraint::class)); } public function testRequiresV3(): void { + $reCaptcha = $this->createMock(ReCaptcha::class); $requestStack = $this->createMock(RequestStack::class); $logger = $this->createMock(LoggerInterface::class); $context = $this->createMock(ExecutionContextInterface::class); @@ -44,13 +47,14 @@ public function testRequiresV3(): void $this->expectException(UnexpectedTypeException::class); $this->expectExceptionMessage('Expected argument of type "EWZ\Bundle\RecaptchaBundle\Validator\Constraints\IsTrueV3",'); - $validator = new IsTrueValidatorV3(true, 'secret', 0.1, $requestStack, $logger); + $validator = new IsTrueValidatorV3(true, 0.1, $reCaptcha, $requestStack, $logger); $validator->initialize($context); $validator->validate('', $this->createMock(IsTrue::class)); } public function testRequiresValueNotNullButNotString(): void { + $reCaptcha = $this->createMock(ReCaptcha::class); $requestStack = $this->createMock(RequestStack::class); $logger = $this->createMock(LoggerInterface::class); $context = $this->createMock(ExecutionContextInterface::class); @@ -62,7 +66,7 @@ public function testRequiresValueNotNullButNotString(): void $this->expectException(UnexpectedTypeException::class); $this->expectExceptionMessage('Expected argument of type "string", "stdClass" given'); - $validator = new IsTrueValidatorV3(true, 'secret', 0.1, $requestStack, $logger); + $validator = new IsTrueValidatorV3(true, 0.1, $reCaptcha, $requestStack, $logger); $validator->initialize($context); $validator->validate(new stdClass(), new IsTrueV3()); }