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

时间:2013-10-22 22:39:14

标签: php linux apache permissions chroot

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

验证后我可以这样做:

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

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

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

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

3 个答案:

答案 0 :(得分:4)

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

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

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

<IfModule mpm_itk_module>
AssignUserId USER GROUP
</IfModule>

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

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

在我看来,vhosts的用户/权限分离似乎是一种更加节俭的方式。

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

编辑:

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

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

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

编辑2:

如同在cament中建议的那样,如果你只使用apache让用户访问上传/操作文件,那么只需将文件放在(!)apache的documentroot树之外,然后创建简单的数据库以了解哪个文件是由哪个用户拥有:

user a | file parentdir/filename

这可能是一个简单的表格,你的php代码从数据库中为用户提供了一个列表,他可以查看/操作哪个文件,你的代码按照用户操作的意图完成工作。

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

编辑3:

哈哈,在我读完你的类似帖子后,我终于得到了你的问题:(How can an Apache user write files when having permissions to do it?) 在这种情况下(在您的网页上有真正的匿名用户),您根本没有机会解决这个问题。每个访问者都是在没有身份验证的情况下处理的。正如我在上一次编辑中假设并在类似帖子中评论的那样:根本不需要处理linux文件权限。

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

第二种方法是使用之前建议的authed用户:创建一个带有用户/密码的db表来登录网页(不是服务器)和另一个保存用户/文件关系的表。在登录网页后,再次使用会话来允许用户访问/操作已上传的文件。

答案 1 :(得分: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并根据您的要求扩展类。

答案 2 :(得分:2)

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

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

为了说明,我创建了一个名为test的帐户,并且可能是一个唯一的目录。如果我退出,我应该无法访问该目录,因为您的代码会看到

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

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

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

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