系统时间不准确造成 IE 下 Kohana 的 Captcha 库验证失败

好糗……

最近玩 Kohana 碰到太多诡异的问题,比如所有模板都要以 UTF8 无 BOM 的编码格式保存,否则 IE 下显示会有问题。自己写的 helper 类也要保存成 UTF8 无 BOM 的编码格式,否则也会出现类似的问题。

这一系列诡异的问题,把我原本清晰的思路也被搞乱了。

测试代码(使用 Kohana 文档上的):

// Load Captcha library, you can supply the name of the config group you would like to use.
$captcha = new Captcha;
// Ban bots (that accept session cookies) after 50 invalid responses.
// Be careful not to ban real people though! Set the threshold high enough.
if ($captcha->invalid_count() > 49)
    exit(‘Bye! Stupid bot.’);
// Form submitted
if ($_POST)
{
    // Captcha::valid() is a static method that can be used as a Validation rule also.
    if (Captcha::valid($this->input->post(‘captcha_response’)))
    {
        echo ‘<p style=”color:green”>Good answer!</p>’;
    }
    else
    {
        echo ‘<p style=”color:red”>Wrong answer!</p>’;
    }
    // Validate other fields here
}
// Show form
echo form::open();
echo ‘<p>Other form fields here…</p>’;
// Don’t show Captcha anymore after the user has given enough valid
// responses. The “enough” count is set in the captcha config.
if ( ! $captcha->promoted())
{
    echo ‘<p>’;
    echo $captcha->render(); // Shows the Captcha challenge (image/riddle/etc)
    echo ‘</p>’;
    echo form::input(‘captcha_response’);
}
else
{
    echo ‘<p>You have been promoted to human.</p>’;
}
// Close form
echo form::submit(array(‘value’ => ‘Check’));
echo form::close();

验证代码在 Firefox 下工作正常,在 IE、Chrome 下都不能正常工作,这肯定就是浏览器之间的差别造成的。

跟踪后发现在 IE 下调用:

Session::instance()->get(‘captcha_response’))

总是返回空。怎么会取不到 Session 的 Cookie?

用 Fiddler 看了看 Cookie,发现 expires 时间比我当前系统的时间,也就是说 Session 类写了一个过期的时间到 Cookie 中,所以总是取不到 Session 的 Cookie 信息。按我的理解,写入一个过期的 Cookie,本就不应该被取到,而 Firefox 下还能取到这条过期的 Cookie,应该算 FF 的一个 Bug 吧。

怎么会出现过期时间?

因为我的 Kohana 是放在虚拟机里跑的,而我的虚拟机长年都是 suspend 而不是 poweroff,所以时间自然要比当前时间慢 = =

这类诡异的问题在 QQ 群上问是几乎不可能找到答案的,所以关键时刻还是得靠自己解决啊。

— EOF —

让 Kohama 支持 Unix Domain Socket 方式连接到 MySQL

我使用的 Kohana 版本为 2.3.1。

虽然数据库配置上留有 socket 的接口,但是配置后仍然不会使用到这个 socket。

只好对框架代码进行修改,如下(粗体部分):

system/libraries/drivers/Database/Mysql.php(mysql 驱动):

  // Build the connection info
// $host = isset($host) ? $host : $socket;
  $port = isset($port) ? ‘:’.$port : ”;
  // Add by Hily to support unix domain socket
  $port = isset($socket) ? ‘:’.$socket : $port;

system/libraries/drivers/Database/Mysqli.php(mysqli 驱动):

  // Build the connection info
// Modified by Hily
  //
$host = isset($host) ? $host : $socket;

  // Make the connection and select the database
// add $socket param by Hily
  if ($this->link = new mysqli($host, $user, $pass, $database, $port, $socket))

严重怀疑 Kohana 的开发团队有没有用过 MySQL,居然犯这种低级错误。

— EOF —