2011年,我从codecanyon购买了一个PHP联系人表单,该表单使用AJAX处理该表单。在今天向他们报告了我的问题后,他们回答说,他们不再为他们的“旧”产品提供支持(通常为他们通常提供的终身支持)……所以他们不会帮助我因此,这篇关于SO的帖子。
我会说这不是正常问题,但我认为将其整理出非常重要-这是(这是我给卖家的电子邮件,但确实解释了问题):
=================
我的AJAX联络表单有一个不寻常的问题(您必须仔细且缓慢地阅读)。
好的,一切正常,但可以100%正常工作...让我解释一下(基本上,这与验证码及其验证有关)
我的网站上有很多页面,每个页面上都有您的在线表单。
现在,我还有一个列表页面,该页面具有链接到所有带有表单的页面的链接。
例:
可以说我在一个列表页面(一个包含到其他页面的全部链接的页面)上,我右键单击“链接A”以在新选项卡中打开页面A ...然后我也右键单击“链接B”以在新标签页中打开页面B。是的,所以我们有列表页面(仍在我面前打开)和另外两个在新标签页中打开的页面(页面A和页面B)...如上所述,这两个页面都有您的在线表单。
现在,我填写两个表格,然后单击提交。
我右键单击以在新选项卡中打开的第一页(页面A)-即使我正确验证了该表单的验证码,也无法正常工作...但是,页面B上的窗体的验证码却可以工作(就像应该这样) 。为什么页面A(我打开的第一页)上的验证码不起作用?
我觉得在整个验证系统中,由于B页是最后打开的,因此验证是考虑到该页面的验证码,并使用该验证码进行验证(整个会话在我的网站上进行浏览),从而使验证码成为第一次打开的页面(页面A)无法正常工作。
所以我做了一个实验:
我重新启动并再次执行相同的操作,即IE:我右键单击链接A在新选项卡中打开页面A ...然后我也右键单击链接B在新选项卡中打开页面B。
我在A页的验证码验证字段中填写了B页的验证码,您知道吗?
所以这是我的问题,因为我知道有些人在网上冲浪(我一直在这样做,也许您也这样做),他们喜欢右键单击链接以在新标签页中打开它们,以便他们稍后浏览后可以返回到他们。列表页面。因此,该用户可能在浏览器中打开了6个标签,并且每个页面都有您的在线表单。如果用户想提交这些表格中的每一个,那么他/她将遇到我在上面报告的确切问题。他们将能够通过1个表单(在新标签页中打开的最后一个页面)进行发送,但除非刷新页面,否则其他页面的验证码将无法工作...但是大多数人不会这样做-而是,他们会认为我的网站出了点问题-我担心。
有针对这个的解决方法吗?
我什至不确定您是否之前注意到了这一点?
我希望我已经清楚地说明了这种情况,如果您能提供帮助,我将不胜感激。
=================
现在回到你身边。是什么原因造成的?
表单工作/处理等需要3个文件(我在这篇文章中不包括CSS文件,而不是表单的html,因为我认为这不是必需的)。
1)process.php
2)image.php(这是验证码)
3)ajax.js
程序PHP
<?php if (!isset($_SESSION)) session_start();
if(!$_POST) exit;
if (!defined("PHP_EOL")) define("PHP_EOL", "\r\n");
$address = "email@example.com";
$bcc = "email@example.com";
$name = $_POST['name'];
$email = $_POST['email'];
$phone = $_POST['phone'];
$comments = $_POST['comments'];
if (isset($_POST['verify'])) :
$posted_verify = $_POST['verify'];
$posted_verify = md5($posted_verify);
else :
$posted_verify = '';
endif;
$session_verify = $_SESSION['verify'];
if (empty($session_verify)) $session_verify = $_COOKIE['verify'];
$error = '';
if(trim($name) == '') {
$error .= '<li>Your name is required.</li>';
}
if(trim($email) == '') {
$error .= '<li>Your e-mail address is required.</li>';
} elseif(!isEmail($email)) {
$error .= '<li>You have entered an invalid e-mail
address.</li>';
}
if(trim($phone) == '') {
$error .= '<li>Your phone number is required.</li>';
} elseif(!is_numeric($phone)) {
$error .= '<li>Your phone number can only contain digits
(numbers and no spaces).</li>';
}
if(trim($comments) == '') {
$error .= '<li>You must enter a message to send.</li>';
}
if($session_verify != $posted_verify) {
$error .= '<li>The verification code you entered is
incorrect.</li>';
}
if($error != '') {
echo '<div class="error_title"><h6><span>Attention!
</span> Please correct the errors below and try again</h6>';
echo '<ul class="error_messages">' . $error . '</ul>';
echo '<div class="close"></div>';
echo '</div>';
} else {
if(get_magic_quotes_gpc()) { $comments = stripslashes($comments); }
$e_subject = 'Booking / Enquiry';
$msg = '<html>
<body style="margin:0; padding:0;">
Name: '.$_POST['name'].'
Email: '.$_POST['email'].'
Contact Number: '.$_POST['phone'].'
Notes: '.$_POST['comments'].'
</body>
</html>';
$msg = wordwrap( $msg, 70 );
$headers = "From: $email\r\nBCC:{$bcc}\r\n" . PHP_EOL;
$headers .= "Reply-To: $email" . PHP_EOL;
$headers .= "MIME-Version: 1.0" . PHP_EOL;
$headers .= "Content-type: text/html; charset=utf-8" . PHP_EOL;
$headers .= 'Content-Transfer-Encoding: 8bit'. "\n\r\n" . PHP_EOL;
if(mail($address, $e_subject, $msg, $headers)) {
echo "<div class='success'>";
echo "<h6>Your Enquiry has been Successfully submitted. </h6>";
echo '<div class="close"></div>';
echo "</div>";
} else {
echo 'ERROR!';
}
}
?>
*请注意,在上面的process.php代码中,我删除了一个似乎可以验证电子邮件地址字段的函数-之所以没有在上面的代码中包括它,是因为它占用了大量代码(会占用很多时间)的空间),我认为没有必要包括
图像
<?php if (!isset($_SESSION)) session_start(); header("(anti-spam-
content-
type:) image/png");
$enc_num = rand(0, 9999);
$key_num = rand(0, 24);
$hash_string = substr(md5($enc_num), $key_num, 5); // Length of
String
$hash_md5 = md5($hash_string);
$_SESSION['verify'] = $hash_md5;
setcookie("verify", $hash_md5, time()+3600, "/");
session_write_close();
$bgs = array("../../img/1.png","../../img/2.png","../../img/3.png");
$background = array_rand($bgs, 1);
$img_handle = imagecreatefrompng($bgs[$background]);
$text_colour = imagecolorallocate($img_handle, 108, 127, 6);
$font_size = 5;
$size_array = getimagesize($bgs[$background]);
$img_w = $size_array[0];
$img_h = $size_array[1];
$horiz = round(($img_w/2)-
((strlen($hash_string)*imagefontwidth(5))/2),
1);
$vert = round(($img_h/2)-(imagefontheight($font_size)/2));
imagestring($img_handle, $font_size, $horiz, $vert, $hash_string,
$text_colour);
imagepng($img_handle);
imagedestroy($img_handle);
?>
AJAX.JS
jQuery(document).ready(function() {
$('.advertform').submit(function() {
var action = $(this).attr('action');
var form = this;
$('.submit', this).attr('disabled', 'disabled').after(
'<div class="loader"></div>').addClass("active");
$('.message', this).slideUp(750, function() {
$(this).hide();
$.post(action, {
name: $('.name', form).val(),
email: $('.email', form).val(),
phone: $('.phone', form).val(),
comments: $('.comments', form).val(),
verify: $('.verify', form).val()
},
function(data) {
$('.message', form).html(data);
$('.message', form).slideDown('slow');
$('.loader', form).fadeOut('fast', function() {
$(this).remove();
});
$('.submit',
form).removeAttr('disabled').removeClass("active");
});
});
return false;
});
$('.message').on('click', function(){
$('.message').slideUp();
});
});
查看上面的代码,有谁能发现可能导致此问题的原因?我假设这可能与javascript有关?
最佳答案
注释是正确的,验证在某些形式上失败,因为该会话仅保存最后生成的验证码的值,因此使在其他选项卡中打开的验证码无效,因为它们在会话中的值被覆盖。因此,任何使用相同或相似代码的人都会遇到此问题。
您可以通过更改会话以存储一组代码而不是仅仅存储一组代码来相当简单地解决它。
在image.php
中,更改:
$_SESSION['verify'] = $hash_md5;
至:
if (!isset($_SESSION['verify'])) $_SESSION['verify'] = array();
$_SESSION['verify'][$hash_md5] = $hash_md5; // *explantion for this array key later
您还可以摆脱为验证码设置的cookie,会话存储应该没问题。
然后在表单处理器中,更改:
if($session_verify != $posted_verify) {
$error .= '<li>The verification code you entered is incorrect.</li>';
}
至:
if(!array_key_exists($posted_verify, $session_verify)) {
$error .= '<li>The verification code you entered is incorrect.</li>';
}
这样一来,您可以在多个标签中打开多个表单,并且仍然能够提交每个表单而不会出现错误的验证码错误。
此外,此代码的另一个问题是成功发布后不会取消设置会话验证值。这意味着一个人可以解决一个验证码,并无限次重复使用旧代码,只要他们在两次提交之间不再访问image.php即可提交您的表单。
要使用阵列版本解决此问题,您需要在验证码和表单处理后取消设置会话密钥。
unset($_SESSION['verify'][$posted_verify]); // remove code from session so it can't be reused
希望能有所帮助。
关于javascript - PHP,AJAX联系表上的Captcha系统问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31991787/