简体   繁体   English

如何使用phalcon / volt表单验证Google reCaptcha v2?

[英]How to validate Google reCaptcha v2 using phalcon/volt forms?

How do you validate the new Google reCaptcha using volt and phalcon techniques? 如何使用伏特和phalcon技术验证新的Google reCaptcha?

(Just wanted to share what I did to make it work, see answer below, hope it helps...) (只是想分享我做的工作,看看下面的答案,希望它有帮助...)

What you will need 你需要什么

  • A Validator (RecaptchaValidator in this case) 验证器(在这种情况下为RecaptchaValidator)
  • Form implementation Form实施
  • Controller implementation (actually no changes needed here, but for completeness...) Controller实现(这里实际上不需要更改,但为了完整性......)
  • View implementation View实施
  • (optional) Config entries for your recaptcha keys and url (nicer/cleaner this way) (可选)配置重新访问密钥和网址的条目(更好/更干净)
  • (optional) A recaptcha element for automatic rendering (if you prefer the render method) (可选)用于自动渲染的recaptcha元素(如果您更喜欢渲染方法)

The Validator 验证者

The validator is the most crucial part of this, all other things are rather intuitive ... 验证器是其中最重要的部分,所有其他事情都相当直观......

use \Phalcon\Validation\Validator;
use \Phalcon\Validation\ValidatorInterface;
use \Phalcon\Validation\Message;

class RecaptchaValidator extends Validator implements ValidatorInterface
{
    public function validate(\Phalcon\Validation $validation, $attribute) 
    {
        if (!$this->isValid($validation)) {
            $message = $this->getOption('message');
            if ($message) { // Add the custom message defined in the "Form" class
                $validation->appendMessage(new Message($message, $attribute, 'Recaptcha'));
            }
            return false;
        }
        return true;
    }

    /********************************************
     *  isValid - Return Values
     *  =======================
     *  true .... Ok
     *  false ... Not Ok
     *  null .... Error
     */
    public function isValid($validation) 
    {
        try {
            $config = $validation->config->recaptcha; // not needed if you don't use a config
            $value =  $validation->getValue('g-recaptcha-response');
            $ip    =  $validation->request->getClientAddress();

            $url = $config->verifyUrl; // or 'https://www.google.com/recaptcha/api/siteverify'; without config
            $data = ['secret'   => $config->secretKey, // or your secret key directly without using the config
                     'response' => $value,
                     'remoteip' => $ip,
                    ];

            // Prepare POST request
            $options = [
                'http' => [
                    'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
                    'method'  => 'POST',
                    'content' => http_build_query($data),
                ],
            ];

            // Make POST request and evaluate the response
            $context  = stream_context_create($options);
            $result = file_get_contents($url, false, $context);
            return json_decode($result)->success;
        }
        catch (Exception $e) {
            return null;
        }
    }
}

Form (class) implementation 表单(类)实现

class SignupForm extends Form
{
    public function initialize($entity = null, $options = null) 
    {
        // Name (just as an example of other form fields)
        $name = new Text('name');
        $name->setLabel('Username');
        $name->addValidators(array(
            new PresenceOf(array(
                'message' => 'Please enter your name'
            ))
        ));
        $this->add($name);

        // Google Recaptcha v2
        $recaptcha = new Check('recaptcha');
        $recaptcha->addValidator(new RecaptchaValidator([
            'message' => 'Please confirm that you are human'
        ]));
        $this->add($recaptcha);

        // Other form fields...
}

Controller implementation 控制器实现

Even though the controller is the same as with every other form, for completeness sake here an example... 尽管控制器与其他形式的控制器相同,但为了完整起见,这里有一个例子......

class SessionController extends \Phalcon\Mvc\Controller
{
    public function signupAction()
    {
        $form = new SignupForm();
        if ($this->request->isPost()) {
            if ($form->isValid($this->request->getPost()) != false) 
            {
                // Add user to database, do other checks, etc.
                // ...
            }
        }

        $this->view->form = $form;
    }
}

View implementation 查看实施

For the view you can either just put the html there or let it be rendered by the engine. 对于视图,您可以将html放在那里或让它由引擎呈现。 If you want it rendered instead (with eg {{ form.render('recaptcha') }} ), you will have to also create an Recaptcha Element instead of using one of the defaults (see last point in this answer for that). 如果你想要它渲染(例如{{ form.render('recaptcha') }} ),你还必须创建一个Recaptcha元素,而不是使用其中一个默认值(参见本答案中的最后一点)。

...

{{ form('class':'signupForm') }}
<fieldset>

    <div>{{ form.label('name') }}</div>
        {{ form.render('name') }}
        {{ form.messages('name') }}

    <!-- other elements here -->        
    <!-- ...                 -->

    <div class="g-recaptcha" data-sitekey="{{ this.config.recaptcha.publicKey }}"></div>
    {{ form.messages('recaptcha') }}

If you don't wanna use a config for your public key (next section), just set the value of the data-sitekey to your personal (Google reCaptcha) public key. 如果您不想使用公钥的配置(下一节),只需将data-sitekey的值设置为您的个人(Google reCaptcha)公钥。

Also don't forget to include the script ( <script src='https://www.google.com/recaptcha/api.js'></script> ) somewhere (eg in your html head section). 另外,不要忘记在某处(例如,在html head部分中)包含脚本( <script src='https://www.google.com/recaptcha/api.js'></script> )。

(Optional) Config (可选)配置

If you wanna use the config to store your recaptcha keys, also add the following to your config/config.php ... 如果你想使用配置存储你的recaptcha键,还要在config/config.php添加以下内容...

// config/config.php

return new \Phalcon\Config([

    'application' => [
        'controllersDir' => __DIR__ . '/../../app/controllers/',
        'modelsDir'      => __DIR__ . '/../../app/models/',
        'formsDir'       => __DIR__ . '/../../app/forms/',
        'viewsDir'       => __DIR__ . '/../../app/views/',
        'pluginsDir'     => __DIR__ . '/../../app/plugins/',
        'libraryDir'     => __DIR__ . '/../../app/library/',
        'cacheDir'       => __DIR__ . '/../../app/cache/',
        'baseUri'        => '/',
    ],

    // other configs here
    // ...

    'recaptcha' => [
        'publicKey' => 'your public key',
        'secretKey' => 'your private key',
        'verifyUrl' => 'https://www.google.com/recaptcha/api/siteverify',
    ],
]);

To be able to access the config in your view, you might also need to add $di->set('config', $config); 为了能够在视图中访问配置,您可能还需要添加$di->set('config', $config); to your dependency injector (typically within config/services.php ). 到你的依赖注入器(通常在config/services.php )。

(Optional) Recaptcha Element (可选)Recaptcha元素

If you want your recaptcha to be rendered for you (instead of you putting the div directly in the view), you will need a separate \\Phalcon\\Forms\\Element\\ ... 如果你想为你渲染你的recaptcha(而不是直接将div放在视图中),你将需要一个单独的\\Phalcon\\Forms\\Element\\ ...

class Recaptcha extends \Phalcon\Forms\Element
{
    public function render($attributes = null) {
        return '<div class="g-recaptcha" data-sitekey="'
            .$this->config->recaptcha->publicKey
            .'"></div>';
    }
}

You will also have to change your Form accordingly: 您还必须相应地更改您的Form

// ...
$recaptcha = new Recaptcha('recaptcha');
$recaptcha->addValidator(new RecaptchaValidator([
    'message' => '...'
]));
// ...

And finally also your View : 最后还有你的View

{{ form.render('recaptcha') }}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM