草庐IT

php随机丢失部分 session

coder 2024-04-16 原文

我正在为 Joomla 开发! 2.5.6 和此代码用于与 Joomla 1.5 一起正常工作

第 1 页

JFactory::getSession()->clear('domain_name', 'dominiForm');

第 2 页

$session = JFactory::getSession();
$session->set('domain_name', $domain_name, 'dominiForm');

第 3 页

$session = JFactory::getSession();
$domain_name = $session->get('domain_name', null, 'dominiForm');

问题是第 3 页有时返回 null,有时返回保存的值。它在我的开发机器上工作正常,但在生产服务器上不行,我不知道该怎么做。

这是服务器上的一些phpinfo()

PHP Version 5.3.3-7+squeeze14
session
Session Support     enabled
Registered save handlers    files user sqlite
Registered serializer handlers  php php_binary wddx

Directive   Local Value Master Value
session.auto_start  Off Off
session.bug_compat_42   Off Off
session.bug_compat_warn Off Off
session.cache_expire    180 180
session.cache_limiter   none    nocache
session.cookie_domain   no value    no value
session.cookie_httponly Off Off
session.cookie_lifetime 0   0
session.cookie_path /   /
session.cookie_secure   Off Off
session.entropy_file    no value    no value
session.entropy_length  0   0
session.gc_divisor  1000    1000
session.gc_maxlifetime  2700    1440
session.gc_probability  0   0
session.hash_bits_per_character 5   5
session.hash_function   0   0
session.name    a6252c638b628a21b4b4b1cf3338a103    PHPSESSID
session.referer_check   no value    no value
session.save_handler    user    files
session.save_path   /var/lib/php5   /var/lib/php5
session.serialize_handler   php php
session.use_cookies On  On
session.use_only_cookies    On  On
session.use_trans_sid   0   0

最佳答案

您正在生产服务器上使用自定义 session.save_handler。可能你不在你的开发机器上。

请注意 Joomla 确实错误地锁定了 session - 没有。从本质上讲,这意味着您是竞争条件的受害者。

如果你看一下the documentaion for session_set_save_handler() ,你会看到有open、close、read、write、destroy和gc(垃圾回收)的回调。

open 应该“初始化”东西,但最重要的是应该获取用于存储的资源的写锁。

read 进行通常的读取,write 进行写入。

close 应该释放写锁。

如果 session 保存处理程序未获取锁,则具有相同 session ID 的多个并行请求可以相互覆盖!

您应该在您的服务器上执行一个简单的测试,看看您是否有这个问题:

<?php

// initialize alternate session save handler here.
//include_once "session-handler.php";

if (isset($_GET['subrequest'])) {
    $starttime = time();
    $subrequest = intval($_GET['subrequest']);

    session_start(); // should wait until lock is released

    echo "<html><pre>";
    echo "Request started on ". date("Y-m-d H:i:s", $starttime)."\n";
    echo "Session locked for this request on ". date("Y-m-d H:i:s"). "\n";
    echo "Executing subrequest ". $subrequest."\n";
    $_SESSION["subrequest"][] = 'collected subrequest #'.$subrequest;
    echo "All subrequests collected:\n";
    var_dump($_SESSION["subrequest"]);
    echo "\nWaiting 1 second\n";

    sleep(1);
    echo "Releasing session lock on ". date("Y-m-d H:i:s"). "\n";
    echo "</pre></html>";
    exit();
}

session_start();

$_SESSION['subrequest'] = array('master request');

?>
<html>
<iframe src="?subrequest=1" width="90%" height="100"></iframe>
<hr>
<iframe src="?subrequest=2" width="90%" height="100"></iframe>
<hr>
<iframe src="?subrequest=3" width="90%" height="100"></iframe>
</html>

此 PHP 文件将初始化 session 并在屏幕上发出三个 iframe,几乎立即再次向服务器发出三个请求。

如果 session 被探测锁定,那么每个 iframe 将在接下来的几秒钟内依次填充。此外,按照出现顺序,$_SESSION['subrequest'] 的控制输出应包括最后返回的子请求的所有子请求。

如果 session 未正确锁定,所有三个 iframe 将在主页加载后一秒内几乎立即填充,并且它们将在调试输出中仅报告它们自己的子请求和主请求。

如果我将此实现用于文件系统存储,我会得到 from the php.net documentation (Example #2)页面,正确保存到 session 失败!

<?php
class FileSessionHandler
{
    private $savePath;

    function open($savePath, $sessionName)
    {
        $this->savePath = $savePath;
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath, 0777);
        }

        return true;
    }

    function close()
    {
        return true;
    }

    function read($id)
    {
        return (string)@file_get_contents("$this->savePath/sess_$id");
    }

    function write($id, $data)
    {
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
    }

    function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }

        return true;
    }

    function gc($maxlifetime)
    {
        foreach (glob("$this->savePath/sess_*") as $file) {
            if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
                unlink($file);
            }
        }

        return true;
    }
}

$handler = new FileSessionHandler();
session_set_save_handler(
    array($handler, 'open'),
    array($handler, 'close'),
    array($handler, 'read'),
    array($handler, 'write'),
    array($handler, 'destroy'),
    array($handler, 'gc')
);

// the following prevents unexpected effects when using objects as save handlers
register_shutdown_function('session_write_close');

如果我看一些 Joomla session 类,我预测存储到 APC、数据库和 XCache 将无法通过此测试,因为它们使用自定义函数而没有实现 open正确关闭

我不熟悉 Joomla,所以您必须自己在这个测试脚本中实现 Joomla 使用 session 的方式。

最后一点:如果无法在数据库中的单个数据集上进行锁定(例如,您正在使用 MyISAM 表),那么实际上您不能使用该表来存储 session 数据。获取表上的锁将停止所有其他 USERS session 。

关于php随机丢失部分 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12686670/

有关php随机丢失部分 session的更多相关文章

  1. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  2. ruby-on-rails - Rails 优雅地处理超时 session ? - 2

    使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p

  3. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

  4. ruby - 如何在 Ruby 中生成一个非常大的随机整数? - 2

    我想在ruby​​中生成一个64位整数。我知道在Java中你有很多渴望,但我不确定你会如何在Ruby中做到这一点。另外,64位数字中有多少个字符?这是我正在谈论的示例......123456789999。@num=Random.rand(9000)+Random.rand(9000)+Random.rand(9000)但我认为这是非常低效的,必须有一种更简单、更简洁的方法来做到这一点。谢谢! 最佳答案 rand可以将范围作为参数:pa=rand(2**32..2**64-1)#=>11093913376345012184putsa.

  5. ruby - Sinatra session 未按预期持续 - 2

    我正在尝试使用Sinatra中的重定向和session在网站周围传递一些数据。这是一个简化的示例,使用PrettyPrint进行调试:require'pp'require'rubygems'require'sinatra'enable:sessionsget'/'dosession[:foo]='12345'puts'session1'ppsessionredirectto('/redir')endget'/redir'doputs'session2'ppsession'helloworld'end查看Thin的输出,我看到:>>Listeningon0.0.0.0:4567,CTRL

  6. ruby-on-rails - 多次选择一个随机数,但绝不会两次选择相同的随机数 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:HowdoIgeneratealistofnuniquerandomnumbersinRuby?我想做的事:Random.rand(0..10).timesdoputsRandom.rand(0..10)end但如果随机数已经显示过,则无法再次显示。如何最轻松地做到这一点?

  7. ruby - 以随机顺序将数组拆分为多个数组 - Ruby - 2

    我试图在每次运行时以随机顺序将一个名称数组拆分为多个数组。我知道如何拆分它们:name_array=["bob","john","rob","nate","nelly","michael"]array=name_array.each_slice(2).to_a=>[["bob","john"],["rob","nate"],["nelly","michael"]]但是,如果我希望它每次都以随机顺序吐出它们怎么办? 最佳答案 在做同样的事情之前,打乱数组。(Array#shuffle)name_array.shuffle.each_s

  8. ruby-on-rails - Ubuntu 14.04 Rails 丢失文件 - 2

    安装Rails时,一切都很好,但后来,我写道:rails-v和输出:/home/toshiba/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in`require':cannotloadsuchfile--rails/cli(LoadError)from/home/toshiba/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in`r

  9. ruby - 如何使用部分字符串搜索数组并返回索引? - 2

    我想使用部分字符串搜索数组,然后获取找到该字符串的索引。例如:a=["Thisisline1","Wehaveline2here","andfinallyline3","potato"]a.index("potato")#thisreturns3a.index("Wehave")#thisreturnsnil使用a.grep将返回完整的字符串,使用a.any?将返回正确的true/false语句,但都不会返回匹配的索引找到了,或者至少我不知道该怎么做。我正在编写一段代码,该代码读取文件、查找特定header,然后返回该header的索引,以便它可以将其用作future搜索的偏移量。如果

  10. ruby - 将 ruby​​ 日期转换为字符串而不丢失格式 - 2

    我正在尝试将RubyDate对象转换为字符串。日期格式为:Sun,15Sep2013但是,当我使用#to_s将其转换为字符串时,它会给出以下内容:"2013-09-15"相反,我希望它变成:"Sun,15Sep2013" 最佳答案 使用Date#strftime有很多选择require'date'date=Date.parse("Sun,15Sep2013")#=>#date.strftime("%a,%d%b%Y")#=>"Sun,15Sep2013" 关于ruby-将ruby​​日期

随机推荐