PHP 无法从 NFS 共享读取会话

Posted

技术标签:

【中文标题】PHP 无法从 NFS 共享读取会话【英文标题】:PHP cannot read sessions from NFS share 【发布时间】:2014-05-16 12:56:48 【问题描述】:

我将我的 php 会话文件存储在 NFS 共享上。问题是,PHP 总是会创建一个空的会话文件,但无法从中读取/写入,因此每次重新加载页面都会创建一个新文件。

如果我将会话存储路径移动到本地文件夹,会话将正常保存。此外,我正在运行具有相同配置的另一个环境,它工作正常。

在 PHP 遇到此问题的同一台服务器上,我能够在保存会话的相同目录中创建/写入/读取文件(使用 root、非 root 和特别是 www-data 用户进行测试)。

我在 Ubuntu 12.04 LTS 上使用 PHP 5.5.12、Apache 2.4.9 和 NFS v3

我的 php.ini

session.save_handler = files
session.save_path = "2;/mnt/cache/sessions"
session.use_cookies = 1
session.use_only_cookies = 0
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 2592000
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 2592000
session.bug_compat_42 = Off
session.bug_compat_warn = Off
session.referer_check =
session.entropy_length = 0
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5

我的 /etc/fstab

nfs-srv.local:/export/cache   /mnt/cache   nfs    rw,hard,intr  0  0

我在 nfs-srv.local 上的 /etc/exports

/export/cache 10.1.10.0/24(rw,nohide,insecure,no_subtree_check,async,all_squash,anonuid=33,anongid=33)

会话文件

ls /mnt/cache/sessions/ -l
drwxrwxrwx 34 nobody nogroup 4096 May 16 10:33 0
drwxrwxrwx 34 nobody nogroup 4096 May 16 10:33 1
drwxrwxrwx 34 nobody nogroup 4096 May 16 10:33 2
...

ls /mnt/cache/sessions/m -l
drwxrwxrwx 2 nobody nogroup 4096 May 16 10:33 0
drwxrwxrwx 2 nobody nogroup 4096 May 16 12:18 1
drwxrwxrwx 2 nobody nogroup 4096 May 16 10:33 2
drwxrwxrwx 2 nobody nogroup 4096 May 16 10:33 3
drwxrwxrwx 2 nobody nogroup 4096 May 16 12:16 4
drwxrwxrwx 2 nobody nogroup 4096 May 16 12:14 5
...

ls /mnt/cache/sessions/m/5 -l
-rw------- 1 nobody nogroup 0 May 16 12:14 sess_m5ifehvhkjdisp7dgtiuu601e2

【问题讨论】:

你能解决这个问题吗?我遇到了同样的问题 是的,我已经修复了它,但只能通过将以下部分添加到 /etc/idmapd.conf [映射] 无名用户 = www-data 无名组 = www-data 【参考方案1】:

我想我已经找到了这个问题的根本原因,我在从 PHP 5.5.10 升级到 5.6.5 时也遇到了这个问题。

PHP 5.5.12 变更日志列出了following bugfix:

当 session.save_path 是每个人都可以写入的目录时 (就像在 Debian 上一样),即使无法找到 现有会话,本地攻击者可以创建一个新的会话文件 使用恶意会话数据,将其 chmod 为 666 并访问任何 webapp 使用他选择的会话 ID 托管在系统上。然后webapp 打开会话文件并将其视为已创建。我的修复: fstat() 会话,检查创建文件的 uid。如果它是 getuid() 和 uid 0 的结果都不是,忽略现有文件。

简而言之,如果他们发现新创建的会话文件不属于运行 Apache 或 root 的用户帐户,他们就会停止写入会话数据。这是相当荒谬的,因为 NFS 在不同级别实现其安全性,但通常使用 remote UID/GID 映射部署,并且经常被压缩。因此,Apache 用户从创建它的微秒开始就不再拥有该文件。这意味着,从 PHP 5.5.12 起(或 5.4.28 包含相同的“修复”),在大多数库存 NFS 服务器上存储会话数据变得不可能。

【讨论】:

【参考方案2】:

使用 idmapd 服务时,所有映射都是通过首先通过/etc/nsswitch.conf 找到用户名/组名来执行的。如果您的 NFS 机器实际上没有可访问的用户名/组名,idmapd 将不会完成映射。

在这种情况下,您似乎在 NFS 客户端计算机和 NFS 服务器上都需要一个 www-data 用户。如果您不想编辑本地 /etc/passwd /etc/group 文件以确保打扰服务器具有 www-data 条目,您可以配置 ldap 或 nis 系统以通过 /etc/nsswitch.conf 管理用户/组域。

看我啰嗦的回答here。

【讨论】:

以上是关于PHP 无法从 NFS 共享读取会话的主要内容,如果未能解决你的问题,请参考以下文章

nfs共享盘无法解析xml

在 centos 7 中无法挂载从 netapp 共享的 nfs 共享

从 Windows 服务访问 NFS 共享

在两个不同的 Web 浏览器之间共享会话

从 java 访问 NFS 共享

检查 NFS 共享是不是在 PHP 中启动