Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
108 views
in Technique[技术] by (71.8m points)

php - ReCaptcha not working properly on iPhone

I have a website with a simple contact form. The validation is somewhat minimal because it doesn't go into a database; just an email. The form works as such:

There are 5 fields - 4 of which are required. The submit is disabled until the 4 fields are valid, and then you can submit it. Then everything is validated on the server again, including the recaptcha (which is not validated by me client side). The whole process is done with ajax, and there are multiple tests that must pass on the server side or 4** headers are returned, and the fail callback handler is called.

Everything works like gangbusters on Chrome on the desktop (I haven't tried other browsers, but I can't imagine why they'd be different), but on the iPhone the reCaptcha always validates even if I don't check the box for the test.

In other words: I still have to fill out the four values correctly in order to submit, but if I don't check the box for the reCaptcha, the request still succeeds.

I can post some code if anyone thinks that would be helpful, but it appears that the problem is with the device and not with the code. Does anyone have any insight into this?


Note: The server side is PHP/Apache if this is helpful.


Update: 5/28/2015:

I'm still debugging this, but it seems like Mobile Safari is ignoring my response headers on my iPhone. When I output the response to the page what I get on Desktop for (data,status,xhr) is:

  1. data: my response which at this point just says error or success -> error

  2. status: error

  3. xhr: {'error',400,'error'}

On Mobile safari:

  1. data: error

  2. status: success

  3. xhr: {'error',200,'success'}

So - it seems like it's just ignoring my response headers. I tried explicitly setting {"headers":{"cache-control":"no-cache"}} but to no avail.


Update: 6/3/2015

Per Request, here is the code. This is almost certainly more than you need. It has also become more obtuse because of the changes I've made to try and fix it. Also note that, while it may appear that there are variables that haven't been defined, they (should) have been defined in other files.

The client side

 $('#submit').on('click', function(e) {

    $(this).parents('form').find('input').each(function() {
        $(this).trigger('blur');
    })
    var $btn = $(this);
    $btn = $btn.button('loading');
    var dfr = $.Deferred();

    if ($(this).attr('disabled') || $(this).hasClass('disabled')) {

        e.preventDefault();
        e.stopImmediatePropagation();
        dfr.reject();
        return false;

    } else {

        var input = $('form').serializeArray();
        var obj = {},
            j;

        $.each(input, function(i, a) {

            if (a.name === 'person-name') {

                obj.name = a.value;

            } else if (a.name === 'company-name') {

                obj.company_name = a.value;

            } else {

                j = a.name.replace(/(g-)(.*)(-response)/g, '$2');
                obj[j] = a.value;

            }

        });

        obj.action = 'recaptcha-js';
        obj.remoteIp = rc.remoteiP;
        rc.data = obj;

        var request = $.ajax({

            url: rc.ajaxurl,
            type: 'post',
            data: obj,

            headers: {
                'cache-control': 'no-cache'
            }

        });

        var success = function(data) {

            $btn.data('loadingText', 'Success');
            $btn.button('reset');
            $('#submit').addClass('btn-success').removeClass('btn-default');
            $btn.button('loading');
            dfr.resolve(data);


        };
        var fail = function(data) {

            var reason = JSON.parse(data.responseText).reason;
            $btn.delay(1000).button('reset');
            switch (reason) {

                case 'Recaptcha Failed':
                case 'Recaptcha Not Checked':
                case 'One Or more validator fields not valid or not filled out':
                case 'One Or more validator fields is invalid':

                    // reset recaptcha

                    if ($('#submit').data('tries')) {

                        $('#submit').remove();
                        $('.g-recaptcha').parent().addBack().remove();

                        myPopover('Your request is invalid.  Please reload the page to try again.');

                    } else {

                        $('#submit').data('tries', 1);
                        grecaptcha.reset();

                        myPopover('One or more of your entries are invalid.  Please make corrections and try again.');
                    }


                    break;

                default:

                    // reset page
                    $('#submit').remove();
                    $('.g-recaptcha').remove();


                    myPopover('There was a problem with your request.  Please reload the page and try again.');

                    break;
            }
            dfr.reject(data);

        };

        request.done(success);
        request.fail(fail);



    }

The Server:

function _send_email(){

$recaptcha=false;
/* * */
if(isset($_POST['recaptcha'])):

    $gRecaptchaResponse=$_POST['recaptcha'];
    $remoteIp=isset($_POST['remoteIp']) ? $_POST['remoteIp'] : false;

    /* ** */
    if(!$remoteIp):

        $response=array('status_code'=>'409','reason'=>'remoteIP not set');
        echo json_encode($response);
        http_response_code(409);

        exit();

    endif;
    /* ** */

    /* ** */
    if($gRecaptchaResponse==''):

        $response=array('status_code'=>'400','reason'=>'Recaptcha Failed');
        echo json_encode($response);
        http_response_code(400);
        exit();

    endif;
    /* ** */

    if($recaptcha=recaptcha_test($gRecaptchaResponse,$remoteIp)):

        $recaptcha=true;

    /* ** */
    else:

        $response=array('status_code'=>'400','reason'=>'Recaptcha Failed');
        echo json_encode($response);
        http_response_code(400);
        exit();

    endif;
    /* ** */

/* * */
else:

    $response=array('status_code'=>'400','reason'=>'Recaptcha Not Checked');
    echo json_encode($response);
    http_response_code(400);
    exit();

endif;
/* * */

/* * */
if($recaptcha==1):

    $name=isset($_POST['name']) ? $_POST['name'] : false;
    $company_name=isset($_POST['company_name']) ? $_POST['company_name'] : false;
    $phone=isset($_POST['phone']) ? $_POST['phone'] : false;
    $email=isset($_POST['email']) ? $_POST['email'] : false;

    /* ** */
    if(isset($_POST['questions'])):

        $questions=$_POST['questions']=='' ? 1 : $_POST['questions'];

        /* *** */

    if(!$questions=filter_var($questions,FILTER_SANITIZE_SPECIAL_CHARS)):

         $response=array('status_code'=>'400','reason'=>'$questions could not be sanitized');
         echo json_encode($response);
         http_response_code(400);
         exit();

        endif;
       /* *** */

    /* ** */
    else:

      $questions=true;

    endif;
    /* ** */

    /* ** */
    if( count( array_filter( array( $name,$company_name,$phone,$email ),"filter_false" ) ) !=4 ):

        $response=array('status_code'=>'400','reason'=>'One Or more validator fields not valid or not filled out');
        echo json_encode($response);
        http_response_code(400);
        exit();

    endif;
    /* ** */

    $company_name=filter_var($company_name,FILTER_SANITIZE_SPECIAL_CHARS);
    $name=filter_var($name,FILTER_SANITIZE_SPECIAL_CHARS);
    $phone=preg_replace('/[^0-9+-]/', '', $phone);
    $email=filter_var($email,FILTER_VALIDATE_EMAIL);

    /* ** */
    if($company_name && $recaptcha && $name && $phone && $email && $questions):

        $phone_str='Phone:  ' . $phone;
        $company_str='Company:   ' . $company_name;
        $email_str='Email String:  ' . $email;
        $name_str='Name:  '.$name;
        $questions=$questions==1 ? '' : $questions;
        $body="$name_str

$company_str

$email_str

$phone_str

____________________

$questions";


        $mymail='[email protected]';
        $headers   = array();
        $headers[] = "MIME-Version: 1.0";
        $headers[] = "Content-type: text/plain; charset="utf-8"";
        $headers[] = "From: $email";
        $headers[] = "X-Mailer: PHP/" . phpversion();

        /* *** */
        if(mail('$mymail', 'Information Request from: ' . $name,$body,implode("
",$headers))):

            $response=array('status_code'=>'200','reason'=>'Sent !');
            echo json_encode($response);
            http_response_code(200);
            exit();

        /* *** */
        else:

            $response=array('status_code'=>'400','reason'=>'One Or more validator fields is invalid');
            echo json_encode($response);
            http_response_code(400);
            exit();

        endif;
        /* *** */

     endif;
    /* ** */

   endif;
  /* * */

     $response=array('status_code'=>'412','reason'=>'There was an unknown error');
     echo json_encode($response);
     http_response_code(412);
     exit();
 }


function recaptcha_test($gRecaptchaResponse,$remoteIp){

    $secret=$itsasecret; //removed for security;

    require TEMPLATE_DIR . '/includes/lib/recaptcha/src/autoload.php';
    $recaptcha = new ReCaptchaReCaptcha($secret);
    $resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp);

    if ($resp->isSuccess()) {
        return true;
            // verified!
    } else {
        $errors = $resp->getErrorCodes();
        return false;
    }
 }
question from:https://stackoverflow.com/questions/30483703/recaptcha-not-working-properly-on-iphone

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Like that question iOS: Authentication using XMLHttpRequest - Handling 401 reponse the easiest way to solve that is disregard natural headers validation and, on the callback sucess, validate with some flag.

I've saw some cases like that and never smell good.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...