簡體   English   中英

PHP 安全性和獨特的命名約定

[英]PHP security and unique naming conventions

像這樣命名用戶上傳的圖像(例如頭像)有什么問題:

/user_id-username.jpg

例子:

/1-feont.jpg

所有圖像都有唯一的名稱(因為 user_id 是主鍵),但是安全性呢? 這有什么不好的影響嗎? 如果有,我應該做哪些約定?

在將用戶名用作文件名的一部分之前,請確保對其進行了適當的清理。 用戶 ID 應該是系統生成的,這樣不會導致任何問題。

你給圖像起的名字純粹是傳統的。 我不認為泄露用戶名是一個安全問題。 (如果是,那么您最好立即檢查您的 CMS,)但是。 如果您的網站不完全安全,黑客可以利用 SQL 注入來訪問您的用戶數據。

但這個想法真的很牽強。 您可以使用用戶名提前 go。 :-)

IMO,只需將圖像命名為user-user_id.jpg (這里,“user”是一個普通字符串,后跟 integer - user_id)

一般來說,這很好,但有些用戶可能不喜歡顯示他們的姓名,並且如果您的站點不完全安全,或者如果將來發現 PHP 漏洞目前未知,則作為主鍵的用戶 ID 可能存在漏洞。

對於這類事情,我傾向於使用以下代碼

$createName = date('YmdHis');
$fileType = '.jpg';
$imgName = $createName.$fileType;

這應該給出一個類似 20110702155513.jpg 的字符串 - 這是圖像命名的完整日期和時間,並且是唯一的。

如果你真的想要安全,那么你可以寫一個回調 function 如果由於文件名不唯一而失敗(通常是因為在同一秒內有 2 個請求 - 不太可能但可能),那么你可以使用回退在字符串中間添加用戶 ID 或使用回退作為您的主要命名方法,例如

if($imgName == 'inuse'){
     $createName1 = date('Ym');
     $createName2 = date('dHis');
     $fileType = '.jpg';
     $imgName = $createName1.$userId.$createName2.$fileType;
}

這允許用戶 ID 被隱藏但完全唯一。

*編輯 - *另一種選擇是使用現有格式並創建一個 MD5 hash,代碼類似於

$user_id = 'user_id';
$username = 'username';
$fileType = '.jpg';
$fileName = md5($user_id).'-'.md5($username).$fileType;

我希望這有幫助

  • 當您有同時上傳的用戶時,使用 Ryan 建議的日期會失敗
  • 當用戶可以更改其用戶名時,使用該用戶名會失敗。 “失敗”在這里有點困難,但是您必須移動文件,這是使用其他解決方案時不需要的東西
  • 如果 ID 是數據庫中自動生成的自動增量 ID,則使用id可以解決所有並發問題。 Kerrek SB相反,我認為這不會在唯一標識符和文件系統上的圖像之間建立聯系。 我的意思是它是獨一無二的,你可以使用它。

如果您經常公開使用 ID,使用 ID 還可以讓您的用戶輕松找到/鏈接他們的圖像。 另一方面,如果您在 URL 中只有用戶名 - 例如/profile/$username ,那么我也會在圖像文件名中使用用戶名 - 保持一致。

關於安全性:如果您清理用戶名,一切都很好。 只要確保它是唯一的,這樣人們就不能覆蓋彼此的名字(這意味着您需要對數據庫中的用戶名使用與圖像文件名中的用戶名相同的衛生規則)。

如果您需要手動查找圖像,使用用戶名作為圖像名稱也可以“更容易”找到圖像,但這可能並不經常發生,對您來說不值得。

總而言之,我將 go 與 ID。

像您在第一個示例中使用的方式命名文件沒有巨大風險,但為了使其更安全,為什么不使用更好的東西,例如

    function Naming($username,$imagename)
{
    $uniq = time() ;
    $name  = $uniq.'-'.$username.'-'.$imagename ;
    return $name ;
}

我認為最好避免使用用戶 ID

唯一的 user_id 就足夠了,你不需要“用戶名”。
問題不在這里,而在於文件數(在一個文件夾中)。
在文件夾中將它們除以 1000(或除以 100):獲取 ID 字符串的第一個、第二個和第三個符號並放入單獨的目錄中:

ID = 10524.jpg  
filename = 1/0/5/10524.jpg

如果算法很難寫,可以試試這個function:

function getStorePath($filename, $base_dir)
{
    //file should have extension
    $ext_pos = strrpos($filename, '.');
    if ($ext_pos===false) return false;

    //extension will be sanitized (filtered actually)    
    $ext = preg_replace("|\W+|", "", substr($filename, $ext_pos+1));
    if (empty($ext)) return false;
    if (in_array($ext, array('php', 'shtml', 'cgi', 'inc', 'module', 'sh', 'sql', 'class'))) return false;

    //filename will be filtered    
    $filename = preg_replace("|\W+|", "", substr($filename, 0, $ext_pos));

    if (empty($filename)) $filename = mt_rand(100000, 999999).round(microtime(true)*1000000);

    //let's create path to the file.
    //we will take first 3 symbols of filename as names of folders    
    $d = realpath($base_dir).'/';

    //first symbol
    $d .= $filename[0].'/';
    if (!file_exists($d))
    {
        $md = mkdir($d, 0755);
        if ($md===false && !file_exists($d)) return false;
    }

    //second symbol
    if (isset($filename[1]))
    {
        $d .= $filename[1].'/';
        if (!file_exists($d))
        {
            $md = mkdir($d, 0755);
            if ($md===false && !file_exists($d)) return false;
        }
    }

    //and third symbol
    if (isset($filename[2]))
    {
        $d .= $filename[2].'/';
        if (!file_exists($d))
        {
            $md = mkdir($d, 0755);
            if ($md===false && !file_exists($d)) return false;
        }
    }

    if (!file_exists($d.$filename.'.'.$ext)) return $d.$filename.'.'.$ext;
    else return false;
}

我通常將我的圖像命名為隨機字符串,然后將其存儲在附加到上傳者 ID 的數據庫中。 您還可以通過這種方式存儲有關圖像的其他數據。

$filename = uniqid('', true). '.jpg';

圖像表

編號 | 用戶 ID | 文件名 | ETC

只有我自己的兩分錢。 如果您要添加更多頭像供用戶選擇,最好使用像 uniqid() 這樣的 function 而不是 user of。 否則,您可以隨心所欲。

不過,我使用用戶 ID 和 time() 的 MD5 hash。 只是偏好問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM