为动态创建每个用户数据的唯一目录并检查是否存在任何冲突

时间:2011-08-09 13:23:12

标签: php web-applications directory unique security

感谢您的所有帮助 - 请参阅原始问题和我的编辑遵循两条线规则(我还不能以新用户身份回答我自己的问题......)。

我环顾四周,问题(here)几乎符合我的问题的目标:

例如,我正在为Web应用程序上的每个用户创建一个用户数据目录;当然,文件夹必须是唯一的,但也是抽象的安全性(例如,使用他们的用户ID,是不合适的。

到目前为止,我已经创建了以下功能;它会生成一个唯一的文件夹名称,检查以确保它不存在并将其分配给变量。如果目录已经存在,它会循环回来:

function generate_unique_userDirectory(){
    $userDirectory = md5(uniqid($uid)); //Generate a unique folder name.
    if (is_dir($userDirectory)) {
        return FALSE; //If the dir exists, report so
    } else {
        return $userDirectory; //Return unique foldername
    }
}

while循环用于继续运行,直到找到未使用的文件夹名称。

while (!$userDirectory = generate_unique_userDirectory()) {
    echo 'folder exists...loop back try another';
    //Try another:
    $userDirectory = generate_unique_userDirectory();
}

有没有更好的方法,我主要担心的是我是否过度复杂的程序?

非常感谢你的时间。


我的发现归功于所有贡献!

感谢@Veger和其他所有人;你的帮助很棒;我已经根据你的建议重新设计了这个功能:

function generate_unique_userDirectory($uid){

        $userDirectory = md5(uniqid($uid));             

            while (is_dir(BASE_URI . "$userDirectory")){

                $userDirectory = md5(uniqid($uid));
            }

            return $userDirectory;

        }//End of generate_unique_userDirectory funcation decleration.

            //Example call to function:
        $userDirectory = generate_unique_userDirectory($uid);

            echo "The generated user directory is: $userDirectory";

正如所建议的那样,我将文件夹名称生成在中的循环中,这使得函数调用变得更加简单。

为了回应你的第二个要点@Veger,我的理解是,当我将'uniqid'函数提供给md5函数时,每次都会产生一个新的字符串(虽然我可能会误解)。

将$ uid传递给generate_unique_userDirectory()的目的是进一步“加盐”生成的字符串,但是,我可能会把它放得太远了!

非常感谢所有 - 第一次在stackoverflow上很棒......

5 个答案:

答案 0 :(得分:2)

明智的解决方案是使用主键或其他一些独特的值。由于这不是使用uniqid的选项(碰撞在实践中应该是不存在的)是有意义的,但你也可以从给定用户的唯一键生成哈希,并且可能将其用于查找机制。

$userDir = "/users/" . md5( $user->id . $user->username . $user->email );

如果您需要格外小心,请确保不要将使用过的数据暴露在任何位置,以便无法重构路径。您还可以使用url重写来将具有特定参数的请求重定向到PHP脚本,从而添加一定程度的安全性。这样你可以做一些事情,比如检查会话,IP等等。

答案 1 :(得分:1)

我对你的设计的一些看法:

  • 正如Wesley已评论generate_unique_userDirectory()表明返回的目录是唯一的。因此,在调用其结果是否为唯一目录之后,您不需要检查...
  • 第二次调用该函数会导致同样的失败,因为新用户的$uid没有更改。
  • 如果 更改,为什么不将while循环放在函数中?所以它总是返回一个唯一的目录。
  • 通过调用循环本身中while - 语句中的函数,导致失败后调用它两次。首先调用循环中的语句中的调用覆盖。

答案 2 :(得分:1)

我的建议:

要获得独特的文件夹:

只需使用user_id的md5创建文件夹。

实现安全:

将文件夹置于脱机状态,而不是放在Web路径上,并创建一个类或脚本来访问每个文件资源。

<强>可扩展性:

通过使用类或脚本访问用户文件,您可以稍后将其用作桥接器以切换到另一种存储机制,如Amazon S3或类似的云服务。

答案 3 :(得分:0)

imho,这是正常的方法。由于md5的碰撞可能性太低,因此大多会进行一次迭代。一个人认为我不喜欢你的代码:

if (is_dir($userDirectory)) {
    return FALSE; //If the dir exists, report so
} else {
    return $userDirectory; //Return unique foldername
}

可能存在具有相同名称的常规文件。最好检查file_exists()

答案 4 :(得分:0)

   function generate_unique_userDirectory($uid){
        $userDirectory = md5(uniqid($uid.time())); //Generate a unique folder name.
        if (is_dir($userDirectory)) {
            return generate_unique_userDirectory($uid); //If the dir exists, report so
        } else {
            return $userDirectory; //Return unique foldername
        }
    }

为什么不让你的函数递归?如果生成的目录已在使用中,则脚本将继续尝试,直到它生成唯一目录。这应该是函数的结果,因此名称; - )