【问题标题】:Captcha session doesnt update sometimes验证码会话有时不更新
【发布时间】:2015-06-27 01:38:28
【问题描述】:

有时,当我刷新包含验证码图像的页面时,验证码图像会加载新字符串,但包含验证码刺痛的session 不会更新!

例如,首先,我的验证码图片显示abcde。接下来,我刷新页面,验证码图像将vwxyz 显示为新的验证码,并且定期将$_SESSION['rand_code'] 的值替换为 vwxyz。但是$_SESSION['rand_code'] 具有相同的值abcde

注意:这个问题有 10% 发生。

catpcha.php:

<?php
if(!session_id() || session_id() == ''){ // i used this because i have started a session before
  session_start();
}
$string = '';

for ($i = 0; $i < 5; $i++) {
    $string .= chr(mt_rand(97, 122));
}

$_SESSION['rand_code'] = $string;

$dir = 'fonts/';

$image = imagecreatetruecolor(80, 29);
$black = imagecolorallocate($image, 0, 0, 0);
$color = imagecolorallocate($image, 0, 100, 90); // red
$white = imagecolorallocate($image, 255, 255, 255);

imagefilledrectangle($image,0,0,299,99,$white);
imagettftext ($image, 21, 8, 16, 23, $color, $dir."Havana.ttf", $_SESSION['rand_code']);

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

调用验证码图片:

<img src="captcha.php?e=<?php echo time() ?>">

【问题讨论】:

  • 你如何确定会话值是错误的?
  • 当你做if(!session_id() || session_id() == ''){ 时它会失败,因为有一个会话ID。所以你的会话永远不会开始,你不能对会话应用值。打开错误报告以查看此内容。
  • 实际上@Ohgodwhy 提出了一个非常有效的观点。接得好!删除 if(!session_id() || session_id() == '') 应该可以解决您的问题。
  • @cmorrissey : echo $_SESSION['rand_code']
  • @Ohgodwhy : 这就是为什么我之前已经开始了一个会话来检查用户登录

标签: php session captcha


【解决方案1】:

我猜您正在从加载 &lt;img&gt; 资源的页面检查 $_SESSION['rand_code'],在这种情况下,您可能会在 10% 的余量内遇到竞争条件,从而更新会话发生在从会话中提取代码的请求之后。

请记住,在 PHP 中,默认会话处理程序将阻塞。因此,同时使用同一会话的两个请求将导致第一个请求获取会话锁,而随后的每个请求都等待该锁被释放,然后才能访问会话。在本地环境开发中,客户端和服务器之间几乎没有延迟,这很有可能是因为您首先加载调用captcha.php 的页面,然后再加载captcha.php

再一次,这一切都假设您在执行 &lt;img src="captcha.php?e=&lt;?php echo time() ?&gt;"&gt; 的同一脚本中执行类似 echo $_SESSION['rand_code'] 的操作

编辑

因此,如果您实际上使用上述方法来检查会话变量并将其与显示的验证码图像进行比较,您可能会遇到这种无序的情况。相反,您想尝试这种方法(您应该会发现您的会话变量根本没有不同步)...

像这样在你的脚本中创建一个表单(比如说它叫做 index.php)...

<form method="post" action="submit.php">
    <input type="text" name="captchaString" />
    <input type="submit" />
</form>

<img src="captcha.php?e=<?=time()?>">

现在,使用以下内容创建 submit.php 脚本...

<?php
session_start(); // always start the session first

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    // if the user POSTs let's check the captcha string against the session
    if (isset($_POST['captchaString']) && $_POST['captchaString'] === $_SESSION['rand_code']) {
        echo "<h1>Success!</h1>";
    } else {
?>
<h1>Failure...</h1>
<p>
Captcha was '<strong><?=$_SESSION['rand_code']?></strong>' and you provided
'<strong><?=$_POST['captchaString']?></strong>'
</p>
<?php
    }
} else {
    // go back to form with captcha and try again
    header('Location: /index.php');
}

index.php 加载您的表单并尝试一下。如果您提交了错误的验证码字符串,它会告诉您。

【讨论】:

  • 我使用(!session_id() || session_id() == '',因为我之前使用session_start()检查用户登录
  • 啊,好的。那讲得通。那么这很可能是我提到的比赛条件。您能告诉我们您是如何验证会话变量不同步的吗?
  • 所以当我删除那个条件时,我得到这个错误:Notice: A session had already been started - ignoring session_start() in captcha.php on line 3
  • 当 echo $_SESSION['rand_code'] 时,有时这个值是以前的值。
  • @AliN11 是的,如果您之前已经开始了会话,那很好。请参阅上面我的答案中的编辑。
猜你喜欢
  • 1970-01-01
  • 2018-05-17
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
相关资源
最近更新 更多