7

在 Web 应用程序中,我想为每个www-data用户创建一个文件夹,并仅授予对该文件夹的写入权限,并且只授予该用户。

验证后我可以做:

mkdir($file->getPath().mt_rand(0,100000),0700);  

$file->getPath()这将在对所有者用户具有所有权限的路径中创建一个具有随机名称的新目录。但它会授予所有 www-data用户权限。

如果我创建一个 chroot 监狱,我必须为每个用户再次复制所有文件,因为我应该创建许多监狱(一个用于用户)。

我对此感到抓狂,并没有找到解决方案。

4

3 回答 3

4

如果我正确理解您的问题,那么您的问题始于 linux 权限/用户框架的结构。因此,拥有 Apache 进程的用户是在运行脚本时创建目录和文件的用户。

如果您需要脚本的用户分离,例如:您的服务器上有不同(虚拟)主机的不同目录,并且您不希望一个主机的脚本作用于同一(apache)服务器上不同主机的数据,那么你应该使用'mpm_itk_module' 而不是更常见的'mpm-prefork' apache。

使用它,您可以定义 apache 在执行任何脚本时使用的用户/组,例如,仅通过此命令为 httpd.conf 中的每个虚拟主机条目创建目录:

<IfModule mpm_itk_module>
AssignUserId USER GROUP
</IfModule>

如果您真的想从 ONE 脚本执行创建不同的目录,则需要 root.root 拥有 apache 进程,然后脚本需要按照您想要的方式为每个目录设置权限和所有者。

但是,在网络服务器上以 root 身份运行即使是最好的脚本也不是一个好主意,因为您可能没有想到任何风险。

在我看来,虚拟主机的用户/权利分离似乎是一种更省钱的方式。

另一点 - 仅限 PHP - 是 suPHP -> http://www.suphp.org

编辑:

好的,我查看了您的网站,即使我不会说西班牙语,看起来您只有一个网站,代表不同的用户始终通过该网页访问。那么 linux 文件系统权限的用户分离需要在哪里呢?您可以通过应用程序限制所有内容,而无需文件系统用户。即使您给予例如额外的 ftp 访问权限 - 例如使用 proftpd 限制它,它也有自己的 chroot mech 供不同用户使用。

只有当您无法控制谁在执行什么时,您才应该关心文件系统权限。这是多域主机上的一个常见问题,您可以使用我提到的 mpm_itk_module 来解决。

也许你应该多描述一下你的情况?

编辑2:

正如评论中所建议的那样,如果您只使用 apache 来让用户访问文件以进行上传/操作,那么只需将文件放在(!)apache 的 documentroot 树之外并创建简单的数据库来知道哪个文件属于哪个文件用户:

user a | file parentdir/filename

这可能是一个简单的表格,您的 php 代码会从数据库中向用户提供他能够查看/操作的文件的列表,并且您的代码会按照用户操作的预期工作。

只要您不让用户通过其他服务(ftp、ssh 等)访问文件,就根本不需要使用 linux 用户权限。只需注意将文件放在服务器的文档根目录之外,这样只有您的 php 代码才能通过服务器的 apache 用户的权限访问这些文件。

编辑 3:

哈哈,在我阅读了您的类似帖子后,现在终于解决了您的问题:(Apache 用户在有权限的情况下如何写入文件?)在这种情况下(您的网页上有真正的匿名用户)您没有机会完全解决这个问题。每个访问者都被视为同一个访问者,无需身份验证。正如我在上次编辑中假设并在类似帖子中评论的那样:根本不需要处理 linux 文件权限。

您的解决方案 ;) :您需要在用户访问您的页面时使用会话 ID 在一个会话中进行文件操作。因此,您的代码需要处理访问者(会话 ID)与他使用此会话 ID 上传的文件之间的关系。使用只要访问者在线就有效的会话 ID 是执行此操作的最佳方式。再一次 - 不需要文件系统权限.... ;)

第二种方法是使用之前建议的经过身份验证的用户:创建一个带有用户/密码的数据库表以登录网页(而不是服务器)和另一个保存用户/文件关系的表。然后,在他登录网页后,再次使用会话以允许用户访问/操作已上传的文件。

于 2013-11-02T12:54:48.903 回答
3

我可以让你用 mod_php 运行 apache。那么这意味着您的 PHP 实例在 apache 实例下工作并且具有 apache USER 和 GROUP。您可以创建文件夹并可以更改此文件夹的所有者,但所有者必须是您系统中的用户(不是 apache 或相同的虚拟用户)。

但是您可以存储在每个目录文件中,例如“.permitions”并放入该文件的虚拟所有者。接下来,您需要过滤对该目录的每次写入(删除、重命名等)尝试,并比较您的虚拟用户和存储在 .permitions 文件中的用户。

示例类(不完整,但足以理解想法):

class UserDirs {
  private $path='/home/vusers';

  public function mkdir($user){
      $d = $this->path.'/'.md5($user);
      mkdir($d);
      file_put_contents($d."/.owner",$user);
  }

  public function checkOwner($user, $dirname){
       $f = $dirname."/.owner";
       $virtual_owner = file_get_contents($f);
       return $user === $virtual_owner;
  }

}

$d = new UserDirs()
$d->mkdir("foo","bar");
echo $d->checkOwner("foo1","bar") === true ? "OK":"FAIL";
echo $d->checkOwner("foo","bar") === true ? "OK":"FAIL";

您可以在此类中封装您需要的所有内容以使用 UserDirs 并根据您的要求扩展类。

于 2013-10-30T12:00:33.940 回答
2

您的用户没有系统帐户。创建这些帐户可能也不可行。因此,我建议通过 Web UI 管理所有这些。

继续按原样创建目录。权限很好。但是,您的用户界面需要更改,以仅显示该用户的目录或文件。我假设您有一个与此页面关联的数据库。将用户名和随机生成的目录名称与用户相关联。如果有人试图转到直接路径,但他们不是与该目录关联的用户,请将他们踢回登录屏幕。

为了说明,我创建了一个名为的帐户test,并且大概被赋予了一个唯一的目录。如果我注销,我将无法访问该目录,因为您的代码会看到

  • 我没有登录,因此无权访问该目录

如果我以身份登录test2并访问 的目录test,您的代码应该会看到

  • 我不是所访问目录的所有者,因此应酌情重定向。

您需要添加一个函数来检查用户正在访问的目录并将其与与用户关联的目录进行比较。如果他们两个匹配,让他们继续。如果它们不匹配,则重定向用户。

于 2013-10-28T19:48:04.920 回答