mewebstudio / captcha

Captcha for Laravel 5/6/7/8/9/10/11
MIT License
2.44k stars 450 forks source link

Captcha validation issue on Ajax Calls #108

Open khalilst opened 7 years ago

khalilst commented 7 years ago

Captcha validation works fine in simple form submit but it always returns false in ajax calls. I did remove the captcha from session as some poeple suggested, but it has no effect. This is my js code:

        var data = {
            _token: token,
            email: form.find('[name="email"]').val(),
            captcha: form.find('[name="captcha"]').val()
        }
        $.post(url, data, function(data) {
            if (data.result == 'OK') {
                form.find('.alert').fadeIn(250);
                red.fadeOut(250);
                setTimeOut(function() {
                    form.closest('popover').fadeOut(500);
                }, 1000);
            } else {
                red.html(data.message).fadeIn(500);
            }
        })

And this is my Laravel code:

    Session::forget('captcha');
    $v = Validator::make(Input::all(), [
        'captcha' => 'required|captcha',
        'email' => 'required|email',
    ]);

I missed something?!

khalilst commented 7 years ago

I found the problem, also other people mentioned it before. First removing the captcha from session is completely worng. Second in the source code after every validation the the captcha goes removed from the session, it's 50% wrong :), because we will need it after validation fails, but it's removed.

So as a temporary solution I suggest store the session before validation and reload only after validation fails. But the permanent solution is correcting the source code by our respected friends @mewebstudio .

Temporary Code could be like this:

        $captcha = Session::get('captcha');
        if (Validator::make(Input::only('captcha'), ['captcha' => 'required|captcha'])->fails()) {
            Session::put('captcha', $captcha);
        }
shanhai3000 commented 7 years ago

我也发现了这个问题,在ajax异步验证的时候只会response false 如果是在form submit提交,http Request请求,使用$this->validate()验证,captcha规则是可行的, 但是如果发起一个ajax request验证,使用Validator::make()->validate()的方法,captcha规则不起作用. 另外,我发现似乎ajax的每一次post提交请求,都会对captcha造成影响,如果使用复制粘贴的方法,一次性在验证码的输入框粘贴完整,正确的验证码,ajax的验证结果是正确的,但是在submit提交的时候会失败,这应该和Validator::make()中的captcha有关,因为如果我在验证规则里把captcha的验证规则取消,就可以正常提交表单. I also discovered the problem of response false only when AJAX is asynchronously validated The captcha rule is feasible while a form submit is submitted, the HTTP Request request is used, and $this->validate () is used to validate it, However, if you launch a Ajax request validation, use the Validator:: make () ->validate () method, and the captcha rule didn't work. In addition, I found that every post submission request for Ajax would have an impact on captcha. If you use copy and paste method, once in the verification code input box to paste the complete, correct verification code, AJAX verification result is correct, but the submit submission callback will fail, it should be Validator:: make (captcha) in, because if I cancel the validation rule of the Captcha, the form can be submitted properly

shanhai3000 commented 7 years ago

我找到了原因并且找到了解决的办法 使用ajax post异步验证会出现false的原因是,在输入captcha之后进行post提交的一瞬间(例如绑定了失去焦点post事件),源代码执行了清除session的动作,源代码是: $this->session->remove('captcha') 这样的话,在点击进行表单提交时,session中已经没有了captcha的key,所以源代码中的check()方法必然会返回false,暂时我的做法是注释掉了这一段代码 // $this->session->remove('captcha'); 然后在登陆的控制器里加上: session()->remove('captcha'); 如果还不放心的话,可以在前端js里给captcha的img添加一个click()事件,让captcha刷新一下.

现在ajax异步验证并提交表单一切OK!

In English: I found the cause and found a solution The reason for the occurrence of false using Ajax post asynchronous authentication is that, after the input authentication code is submitted for post submission(for example, a lost focus post event is bound), the source code performs the action of clearing the session, and the source code is:$this->session->remove('captcha') In this case, when you click on the form submission, there is no captcha key in the session, so the check () method in the source code will definitely return false, and for the time being I'm commenting on the missing piece of code // $this->session->remove ('captcha');' Then add the controller to the landing:session () ->remove ('captcha'); If you're still worried, you can add a click () event to the captcha's img in the front of the JS to refresh the captcha

Now Ajax asynchronously validates and submits the form, all OK!

By.istheprince

sheaxiang commented 7 years ago

@istheprince 请问一下,laravel5.5的版本,按照您的方法操作,还是验证失败,有遇到过这种情况吗?

shanhai3000 commented 7 years ago

@sheaxiang 我就在用5.5,你是什么情况呢?

heimuya commented 6 years ago

还有一种解决方式。通过修改app/Http/Kernel.php中的middleware如下:

protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\Cors::class,
        \Illuminate\Session\Middleware\StartSession::class, // 将Session添加到每一个请求中
    ];

其他内容都不需要修改,即可解决ajax验证码验证的问题。

tsurumure commented 6 years ago

@istheprince 请问一下, 5.1版本,注释掉了 $this->session->remove('captcha'),控制器添加了 session()->remove('captcha');,使用 ajax 还是返回 false。这是还需要做哪些步骤吗

jcanchor commented 6 years ago

Thanks zhangqi1990! I was having trouble with an Ajax contact form and your answer Sep 3, 2017 was the answer that fixed my problem along with explanation of why the check() method was firing. I implemented your fix and now the form works as users would expect.

qingyi12345 commented 6 years ago

@heimuya
laravel5.6中的$middleware中加上\Illuminate\Session\Middleware\StartSession::class, // 将Session添加到每一个请求中,我再vue中使用的代理请求接口还是验证返回失败?? public function check($value) { if ( ! $this->session->has('captcha')) { return false; } ..... } 这个方法中直接返回false;

singhsnt commented 5 years ago

how i can get captcha value ?? which is generated?

jcanchor commented 5 years ago

how i can get captcha value ?? which is generated?

Set up your config/app.php file properly:

Package service providers Mews\Captcha\CaptchaServiceProvider::class,

Aliases 'Captcha' => Mews\Captcha\Facades\Captcha::class,

Then in your form you can call: <?php echo Captcha::img('flat'); ?>

The img options are defined in your config/captcha.php file where you can find these options: default, flat, mini or inverse

See the instructions and details for setup on the <> code page for more ways to use the package.

singhsnt commented 5 years ago

okay i will try. I need captcha to match user entered captcha and generated captcha same then validate and user register sucessfully

On Wed, Dec 5, 2018 at 12:10 AM Jim Adamek notifications@github.com wrote:

how i can get captcha value ?? which is generated?

Set up your config/app.php file properly:

Package service providers Mews\Captcha\CaptchaServiceProvider::class,

Aliases 'Captcha' => Mews\Captcha\Facades\Captcha::class,

Then in your form you can call: <?php echo Captcha::img('flat'); ?>

The img options are defined in your config/captcha.php file where you can find these options: default, flat, mini or inverse

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mewebstudio/captcha/issues/108#issuecomment-444209994, or mute the thread https://github.com/notifications/unsubscribe-auth/Ako8NPj_YCADFBLWt9iR1hlP1826ATrNks5u1sGXgaJpZM4PG82X .

singhsnt commented 5 years ago

is captcha value stored in session??

On Wed, Dec 5, 2018 at 1:25 PM vikas singh mailtovikas453@gmail.com wrote:

okay i will try. I need captcha to match user entered captcha and generated captcha same then validate and user register sucessfully

On Wed, Dec 5, 2018 at 12:10 AM Jim Adamek notifications@github.com wrote:

how i can get captcha value ?? which is generated?

Set up your config/app.php file properly:

Package service providers Mews\Captcha\CaptchaServiceProvider::class,

Aliases 'Captcha' => Mews\Captcha\Facades\Captcha::class,

Then in your form you can call: <?php echo Captcha::img('flat'); ?>

The img options are defined in your config/captcha.php file where you can find these options: default, flat, mini or inverse

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mewebstudio/captcha/issues/108#issuecomment-444209994, or mute the thread https://github.com/notifications/unsubscribe-auth/Ako8NPj_YCADFBLWt9iR1hlP1826ATrNks5u1sGXgaJpZM4PG82X .

singhsnt commented 5 years ago

if not how i can store it in session and than i can get it??

On Wed, Dec 5, 2018 at 1:48 PM vikas singh mailtovikas453@gmail.com wrote:

is captcha value stored in session??

On Wed, Dec 5, 2018 at 1:25 PM vikas singh mailtovikas453@gmail.com wrote:

okay i will try. I need captcha to match user entered captcha and generated captcha same then validate and user register sucessfully

On Wed, Dec 5, 2018 at 12:10 AM Jim Adamek notifications@github.com wrote:

how i can get captcha value ?? which is generated?

Set up your config/app.php file properly:

Package service providers Mews\Captcha\CaptchaServiceProvider::class,

Aliases 'Captcha' => Mews\Captcha\Facades\Captcha::class,

Then in your form you can call: <?php echo Captcha::img('flat'); ?>

The img options are defined in your config/captcha.php file where you can find these options: default, flat, mini or inverse

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mewebstudio/captcha/issues/108#issuecomment-444209994, or mute the thread https://github.com/notifications/unsubscribe-auth/Ako8NPj_YCADFBLWt9iR1hlP1826ATrNks5u1sGXgaJpZM4PG82X .

jcanchor commented 5 years ago

if not how i can store it in session and than i can get it??

You can check your session variables in controller that processes your form with:
dd($request, Session::All());

You can add your captcha variable to session with: Session::put('captcha', $captcha);

Refer to https://laravel.com/docs/master/session#using-the-session or

https://learninglaravel.net/cheatsheet/#sessions

singhsnt commented 5 years ago

Thanks jim. Problem is solved

On Wed, Dec 5, 2018 at 11:31 PM Jim Adamek notifications@github.com wrote:

if not how i can store it in session and than i can get it??

You can check your session variables in controller that processes your form with: dd($request, Session::All());

You can add your captcha variable to session with: Session::put('captcha', $captcha);

Refer to https://laravel.com/docs/master/session#using-the-session http://url or

https://learninglaravel.net/cheatsheet/#sessions http://url

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mewebstudio/captcha/issues/108#issuecomment-444582570, or mute the thread https://github.com/notifications/unsubscribe-auth/Ako8NJgR7U2ajyRKxJQVCnQg67FvX2lzks5u2AoBgaJpZM4PG82X .