区分每个 apache 用户并授予权限


Differentiate each apache user and give permissions

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

验证后,我可以做:

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

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

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

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

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

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

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

<IfModule mpm_itk_module>
AssignUserId USER GROUP
</IfModule>

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

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

在我看来,通过vhosts进行用户/右分离似乎是一种更节省的方式。

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

编辑:

好的,我

看了一下你的网站,即使我不会说西班牙语,看起来你只有一个网站,为通过这个网页的不同用户提供服务。那么,在 linux 文件系统权限上需要用户分离的地方在哪里呢?您可以按应用程序限制所有内容,而无需文件系统用户。即使您提供例如额外的ftp访问权限 - 限制它,例如使用proftpd,它也有自己的chroot机甲供不同的用户使用。

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

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

编辑2:

正如 coment 中所建议的,如果您只使用 apache 让用户访问文件以进行上传/操作,那么只需将文件放在 apache 的文档根树之外(!),并创建简单的数据库以了解哪个文件归哪个用户所有:

user a | file parentdir/filename

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

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

编辑3:

哈,现在在我读了你的类似帖子后,我终于得到了你的问题:(Apache用户在有权写文件的情况下怎么能写文件?在这种情况下(您的网页上有真正的匿名用户),您根本没有机会解决这个问题。每个访客都作为同一访客处理,无需身份验证。正如我在上一篇 EDIT 中假设的那样,并在类似的帖子中评论:根本不需要处理 linux 文件权限。

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

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

我可以让你用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 并根据您的要求扩展类。

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

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

为了说明这一点,我创建了一个名为 test 的帐户,并可能获得了一个唯一的目录。如果我注销,我应该无法访问该目录,因为您的代码会看到

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

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

  • 我不是正在访问的目录的所有者,因此应根据需要重定向。

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