captcha icon indicating copy to clipboard operation
captcha copied to clipboard

New captcha generated regardless of validation results

Open jcanchor opened this issue 6 years ago • 0 comments

I have a fairly complex form that uses captcha. Even if the user gets the correct captcha entered and validated, Mews Captcha generates a new captcha. Most users will not notice that captcha changed and they end up having to re-enter again. This becomes frustrating to the user trying to complete the form.

Once captcha passes validation I want the same captcha to be used for the remainder of the session until the form is successfully submitted. If you would rather have the captcha removed from the form once it passes validation, then the rest of this discussion is not necessary.

I looked at the public function check($value) in src/Captcha.php and saw it was being used by a helper function called captcha_check($value). I do not understand the code enough to know what you are trying to accomplish with that.

I developed my own workaround with a new session variable I created on the server side called captchacontrol. Here is the helper method I call from my form.blade.php before the form is displayed. It is crude since I am testing for the words 'security code' which are in my custom message when captcha fails.

    /**
     * Has captcha passed validation or failed?
     * @param  object $errors  message bag of errors returned
     * @param  string $captcha captcha value entered by user
     * @return string          return correct captcha value to resubmit or empty string if failed
     */
    public static function checkCaptcha($errors, $captcha)
    {
        $errorCap = $errors->first('captcha');
        if (substr_count($errorCap, 'security code') == 1) { 
            Session::put('captchacontrol', 'createnew');  $retCaptcha = ''; }
        else { Session::put('captchacontrol', $captcha);  $retCaptcha = $captcha; }

        return $retCaptcha;
    }

These are the changes I made in src/Captcha.php

First, I added a function keep($bag) below the existing function generate() and duplicated the session put portion with the $bag I want resubmitted.

    /**
     * Keep existing captcha text - this is an addition
     * along with lines 233 - 243 above
     * 
     * @param  string $bag keep existing captcha session
     * @return  string  
     */
    protected function keep($bag)
    {
        $this->session->put('captcha', [
            'sensitive' => $this->sensitive,
            'key'       => $this->hasher->make($this->sensitive ? $bag : $this->str->lower($bag))
        ]);

        return $bag;
    }

Then above in function create($config = 'default') I made changes in the code around this line: $this->text = $this->generate();. It now looks like this.

        if ($this->session->has('captchacontrol')) {
            $control = $this->session->get('captchacontrol');
        } else {
            $control = 'none';
        }

        if (($control == 'none') || ($control) == 'createnew')) {
            $this->text = $this->generate();
        } else {
            $this->text = $this->keep($control);
        }

My captcha control is looking to see if the value is equal to createnew or if it has the value of the captcha that passed validation. In the first case I want a new captcha generated, and in the second I want to return the captcha that has already passed.

I hope this helps someone else looking for a possible solution. I love the Mewes Captcha and the use of Intervention\Image\ImageManager. I appreciate that the flexibility and simplicity of this program. Thanks!!

jcanchor avatar Mar 23 '18 05:03 jcanchor