【问题标题】:Captcha validation in PHP HTML contact formPHP HTML 联系表单中的验证码验证
【发布时间】:2019-07-03 11:26:56
【问题描述】:

几天来,我正在将验证码实施到我的联系表单中。我经历了多个教程和 stackoverflow 讨论,但似乎我仍然做错了什么(我对 PHP 还不是很有经验,所以可能我错过了一些东西)。

a) 我的联系表工作正常(发送电子邮件、检查空白字段等)

b) 验证码显示正确

c) Captcha 验证工作

对于联系表单,我使用 3 个文件 - .html 文件 - 包含网页和两个 .php 文件(用于创建验证码的 captcha.php,用于发送电子邮件和验证的 send-email.php)。

1) kontakt.html:

<!DOCTYPE html><html lang="de">
<head>...</head>
<body>
<div class="contact-form-container">
                            <form  class="contact-form" action="php/send-email.php"  method="post" novalidate>
                                <div class="row">
                                    <div class="column width-6">
                                        <input type="text" name="fname" class="form-fname form-element large" placeholder="Firma*" tabindex="1" required>
                                </div>
                                <div class="column width-6">
                                    <input type="text" name="lname" class="form-lname form-element large" placeholder="Ihr Name*" tabindex="2" required>
                                    </div>
                                    <div class="column width-6">
                                        <input type="email" name="email" class="form-email form-element large" placeholder="E-Mail Adresse*" tabindex="3" required>
                                    </div>
                                     <div class="column width-6">
                                        <input type="tel" name="telefonnummer" class="form-website form-element large" placeholder="Telefonnummer*" tabindex="4" required>
                                    </div> 
                                </div>
                                <div class="row">
                                    <div class="column width-12">
                                        <div class="field-wrapper">
                                            <textarea name="message" class="form-message form-element large" placeholder="Nachricht*" tabindex="7" required></textarea>
                                        </div>
                                    </div>
                                     <div class="column width-6">
                                        <input type="text" name="honeypot" class="form-honeypot form-element large">
                                    </div>           
                                       <div class="elem-group column width-12">
                                           <label for="captcha">Captcha</label>
                                           <img src="php/captcha.php" alt="CAPTCHA" class="captcha-image"><i class="form fas fa-redo refresh-captcha"></i>
                                           <br><br>
                                           <input class="form-message form-element" type="text" id="captcha" name="captcha_challenge" pattern="[A-Z]{6}">                   
                                       </div>
                                    <div class="column width-12">                                           
                                           <input  type="submit" value="Senden" class="form-submit button medium bkg-theme bkg-hover-theme color-white color-hover-white">
                                    </div>              
                                </div>
                            </form>
                            <div class="form-response center"></div>           
                        </div>
</body> 
</html>

2)captcha.php(生成验证码图像,据我所知它可以正常工作)

<?php

session_start();

$permitted_chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ';

function generate_string($input, $strength = 10) {
    $input_length = strlen($input);
    $random_string = '';
    for($i = 0; $i < $strength; $i++) {
        $random_character = $input[mt_rand(0, $input_length - 1)];
        $random_string .= $random_character;
    }

    return $random_string;
}

$image = imagecreatetruecolor(200, 50);

imageantialias($image, true);

$colors = [];

$red = rand(125, 175);
$green = rand(125, 175);
$blue = rand(125, 175);

for($i = 0; $i < 5; $i++) {
  $colors[] = imagecolorallocate($image, $red - 20*$i, $green - 20*$i, $blue - 20*$i);
}

imagefill($image, 0, 0, $colors[0]);

for($i = 0; $i < 10; $i++) {
  imagesetthickness($image, rand(2, 10));
  $line_color = $colors[rand(1, 4)];
  imagerectangle($image, rand(-10, 190), rand(-10, 10), rand(-10, 190), rand(40, 60), $line_color);
}

$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);
$textcolors = [$black, $white];

$font = 'arial.ttf';

$string_length = 6;
$captcha_string = generate_string($permitted_chars, $string_length);

$_SESSION['captcha_text'] = $captcha_string;

for($i = 0; $i < $string_length; $i++) {
  $letter_space = 170/$string_length;
  $initial = 15;

  imagettftext($image, 24, rand(-15, 15), $initial + $i*$letter_space, rand(25, 45), $textcolors[rand(0, 1)], $font, $captcha_string[$i]);
}

header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>

3) send-email.php(发送电子邮件并进行验证)

<?php
// Your Email
    $recipient = "mymail"; 


    // Check $recipient
    if($recipient === '') {
        returnAndExitAjaxResponse(
            constructAjaxResponseArray(
                FALSE,
                'RECIPIENT_IS_NOT_SET',
                array('error_message'=> 'RECIPIENT email address is not set. Please configure the script.')
            )
        );
    }

if ($_POST['captcha_challenge'] == $_SESSION['captcha_text']) {


    // Check for empty required field
    if(!isset($_POST["email"]) || !isset($_POST["fname"]) || !isset($_POST["message"])) {
        returnAndExitAjaxResponse(
            constructAjaxResponseArray(
                FALSE,
                'MISSING_REQUIRED_FIELDS',
                array('error_message'=> 'MISSING_REQUIRED_FIELDS should not be occurred.')
            )
        );
    }

    // Sanitize input
    $fname  = filter_var($_POST["fname"], FILTER_SANITIZE_STRING);
    $lname  = filter_var($_POST["lname"], FILTER_SANITIZE_EMAIL);
    $email = filter_var(trim($_POST["email"]), FILTER_SANITIZE_EMAIL);
    $message = filter_var($_POST["message"], FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);


    // Headers
    $headers = 'From: '.$fname.' <'.$email.'>' . "\r\n";
    $headers .= 'Reply-To: '.$email.'' . "\r\n";
    $headers .= 'X-Mailer: PHP/' . phpversion();

    // Subject
    $subject = "Neue E-Mail von Kontakt Formular";

    // Build Message
    $email_content = "Firma: $fname\n";
    $email_content .= "Ihr Name: $lname\n";
    $email_content .= "Telefon nummer: $telefonnummer\n"; 
    $email_content .= "Email: $email\n\n";
    $email_content .= "Nachricht:\n$message\n\n\n";
    $email_content .= "CLIENT IP:\n".get_client_ip()."\n";
    $email_content .= "HOST IP:\n".$_SERVER['SERVER_ADDR']."\n";

else {
    } echo '<p>Captcha verification is wrong. Take other action.</p>';

}


// Check if sent
try {
    $sendmailResult = mail($recipient, $subject, $email_content, $headers);
    if( $sendmailResult === TRUE ) {
        returnAndExitAjaxResponse(
            constructAjaxResponseArray(
                TRUE
            )
        );
    } else {
        returnAndExitAjaxResponse(
            constructAjaxResponseArray(
                FALSE,
                'ERROR_AT_PHPMAIL',
                array('error_information'=> error_get_last() )
            )
        );
    }
} catch (Exception $_e) {
    returnAndExitAjaxResponse(
        constructAjaxResponseArray(
            TRUE,
            'ERROR_AT_PHPMAIL',
            array('error_message'=> $_e->getMessage())
        )
    );
}


function constructAjaxResponseArray ($_response, $_message = '', $_json = null) {
    $_responseArray = array();
    $_response = ( $_response === TRUE ) ? TRUE : FALSE;
    $_responseArray['response'] = $_response;
    if(isset($_message)) $_responseArray['message'] = $_message;
    if(isset($_json)) $_responseArray['json'] = $_json;

    return $_responseArray;
}

function returnAndExitAjaxResponse ($_ajaxResponse) {
    if(!$_ajaxResponse){
        $_ajaxResponse = array('response'=>false,'message'=>'Unknown error occurred.');
    }
    header("Content-Type: application/json; charset=utf-8");
    echo json_encode($_ajaxResponse);
    die();
}


// Function to get the client IP address
function get_client_ip() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP'])) {
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    } else if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else if(isset($_SERVER['HTTP_X_FORWARDED'])) {
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    } else if(isset($_SERVER['HTTP_FORWARDED_FOR'])) {
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    } else if(isset($_SERVER['HTTP_FORWARDED'])) {
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    } else if(isset($_SERVER['REMOTE_ADDR'])) {
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    } else {
        $ipaddress = 'UNKNOWN';
    }
    return $ipaddress;
}

现在,如果我将验证码字段留空,则电子邮件会从联系表发送到邮件电子邮件地址。但是,如果我在 captcha_challenge 字段中输入任何内容(无论它是否正确),那么联系表单在提交后会冻结并且不会发送电子邮件。

我认为这部分 send-email.php 代码出错的原因(尽管如此,我不知道如何修复它):

if ($_POST['captcha_challenge'] == $_SESSION['captcha_text']) { 
//code 
else {
        } echo '<p>Captcha verification is wrong. Take other action.</p>';

    }

我尝试了许多不同的选项来验证此验证码或使用许多其他验证码想法。现在我一无所知,因为我有限的 php 知识又是失败的测试的一天。

谢谢!

【问题讨论】:

  • 你为什么不用谷歌的reCaptcha?
  • 在比较它们之前先做一个var_dump($_POST['captcha_challenge']);var_dump($_SESSION['captcha_text']);,看看它们包含什么。
  • send-email.php 文件存在语法错误
  • @MilanG 没有帮助。除了进行重新验证可能需要很长时间(有时点击 10 到 20 秒)这一事实之外,并不是每个人都愿意使用 3rd 方解决方案或强迫他们的客户训练 Google 的机器学习算法。

标签: php html


【解决方案1】:

您在 send-email.php 上缺少 session_start();

【讨论】:

  • 谢谢,不知道我是怎么错过的。它现在几乎可以工作 - 如果用户输入正确的验证码,则发送电子邮件。但是,如果验证码不正确,则提交后冻结,我已更改 'else { echo '

    验证码验证错误。采取其他行动。

    '; }' into else { die(Captcha 验证错误。采取其他措施。)'; } 但在提供错误的验证码后仍然不会自行取消。
  • 我用另一种方式。 if $captcha != $userCaptcha 然后取消执行并返回错误。
【解决方案2】:

我在这里粘贴 captcha.php

 <?php
$post = [
   'secret' => '6LfcOEcUAAAAABldSkevRJL75VSrvheVbc_4z9wU', //Enter the secret key provided by the google (just copy and paste it)
   'response' => $_POST['googleResponse'],

];
$ch = curl_init();
echo 
curl_setopt($ch, CURLOPT_URL, 'https://www.google.com/recaptcha/api/siteverify');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$response = curl_exec($ch);
var_export ($response);
// echo $response;
?>

captcha.js 在这里

////////   GOOGLE RECAPTCHA CLIENT SIDE AND SERVER SIDE VERIFICATION   /////////////

            //----------------------------------------------------/
           // onloadCallback()
          // this 
         //----------------------------------------------------/




 var onloadCallback = function() {
        grecaptcha.render('html_element', {    // oncallback render a div with id html_element
          'sitekey' : '6LfcOEcUAAAAAAia1cMp60bnm1PMaFrmJ808il_D', // sitekey for the  captcha 
          'theme' : 'light',           // change the theme for light and dark
          'widgetId': 'widgetId',      // add widget id attribute which is optional
          callback(){
            console.log( 'another callback function here');

             response = grecaptcha.getResponse();    // get the value of response when user submits recaptcha
            console.log('response from google : ', response);

            // send post method to captcha php that is usin curl post request for cross domain
             $.post("captcha.php",
                    {
                      googleResponse: response     // pass the google response

                    },
                      function(response, status){   // pass two parameters respnse  and status 
                           console.log("response after ssv : ", response, status); 

                           if ( status == 'success'){
                             captchaSuccess = status;
                             captchares = captchaSuccess;
                            console.log("captchaSuccess :", captchaSuccess);


                           }
                           // alert response and the status here after verification from google 
                      });
            }
        });
    };

这是我的 index.php

<!DOCTYPE html>
<html>
<head>
  <title>captcha</title>
  <link rel="stylesheet" type="text/css" href="">
</head>
<body>
<div id="html_element"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
        async defer>
    </script>
<script src="captcha.js"></script>
</body>
</html>

使用这个 sn-p 包括验证码验证。您只需将其包含在您的代码中即可开始使用,它仅包含与验证码相关的代码,没有任何额外内容。希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2013-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    相关资源
    最近更新 更多