為什么數據庫ID不能作為URL中的標識符


最近公司在進行網站的SEO優化,將所有主要頁面的URL統一更改為新的格式,其中重要的一項改變是將所有URL的標識符統一為ID,例如過去我們的一個用戶的公共頁面URL是這樣的

https://www.example.com/user/[:username]

而更新后的格式則變成

https://www.example.com/user/[:user_id]

在看到設計文檔(Design Doc)的同時,我本能就對這個這樣的URL形式產生了一絲疑慮,但又說不上為什么。

我們的用戶信息是存在MySQL數據庫的表單中,user_id是一個整數類型的主鍵(Primary Key),同時也是自增(Auto Increment)字段。

從安全角度來說,使用user_id來作為標識符的URL設計並沒有什么問題,但是這樣會有別的問題,什么樣的問題呢?

暴露商業數據!

暴露的數據1:總體用戶數量

有心人如果想要知道公司現在的總體用戶數量,那么很簡單,只需要注冊一個新用戶,然后查看自己的公共主頁,這樣新用戶的user_id就會暴露出來,而這個user_id就約等於網站現在的總體用戶數量(有一部分被刪除的用戶除外)

暴露的數據2:用戶增速

如果說暴露總量還不是最危險的,用戶增速則是更加重大的信息暴露。有心人知道URL中的user_id規律之后,可以通過做很簡單的實驗

1. 創建一個新用戶,查看URL中的用戶ID。 https://www.example.com/user/1000000

2. 隔一段時間之后(一周/月),再創建一個新用戶,查看URL中的用戶ID。https://www.example.com/user/1005000

二者相減(1005000-1000000)就可以輕易得到這段時間內的用戶增長量。甚至可以在外部用很小的代價獲得非常精確的用戶增長曲線。

而這樣的數據,對於大部分公司來說,都是非常核心的數據,尤其在公司未上市之前,應該盡量避免此類數據外流。

這樣的情況十分普遍,因為在學習Web開發的初級教程中,幾乎都會將數據庫主鍵ID用來作為URL標識符,這樣從URl解析主鍵到后台服務使用主鍵查詢數據庫,可以非常簡潔直觀。但是在實際的生產環境中,這樣的做法往往並不可取。

那么有什么樣的方法可以避免使用數據庫ID呢?

1. 使用UUID —— UUID是亂序的字符串,所以無法用來預測數據,我們可以用多種方法來設計UUID。如果你使用了MongoDB等NoSQL的存儲,那么恭喜你獲得了天然的UUID,每一個ObjectID都是你可以使用的UUID。如果你的數據依然離不開關系數據庫,那么可以考慮在數據庫中擴增字段來生成UUID並存儲,同時提供基於UUID的查詢接口。

2. 加密自增ID —— 在系統已經到處使用自增ID作為內部查詢的關鍵詞的情況下,往往遷移到UUID會帶來很大的工程開銷,並且為了支持已有的URL訪問,還需要維護兩套不同的邏輯。在這種情況下一種相對簡便的方法是在服務器端在生成URL的時候對於ID進行加密,這樣在客戶端看到的便是加密后的ID。當客戶端進行請求的時候,服務器端再進行解密。這樣的方法看似簡單,其實其中也多需要注意的地方,比如加密的秘鑰一旦泄露,便失去了意義。並且有在網頁端動態生成URL的需求,也有不小的挑戰。

(本文的部分觀點源自 https://medium.com/lightrail/prevent-business-intelligence-leaks-by-using-uuids-instead-of-database-ids-on-urls-and-in-apis-17f15669fd2e


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM