2009-11-11 121 views
13

我在考慮如何將密碼存儲在數據庫中:在CHAR(40)字段中適當地醃製SHA1字符串。但是,由於其中的字符數據實際上只是160位數的十六進制表示,所以我認爲將它存儲爲BINARY(20)可能會更好。在MySQL中將十六進制值存儲爲二進制文件

CREATE TABLE users (
    password BINARY(20) 
    /* snip */ 
); 

INSERT INTO users (password) VALUES (UNHEX(SHA1('mypassword')); 

在我看來,這種方法的一個好處是,它半部場的大小,但我能想象可能有一些缺點太多。

您的意見是?

+0

每個密碼只能保存幾個字節。這值得麼? – pavium 2009-11-11 04:09:41

+1

這就是我想知道的。好處可能很渺茫,但成本是多少? – nickf 2009-11-11 04:20:42

+0

好吧,似乎有一般的協議,好處是輕微的,沒有人建議任何重大成本。如果您進行了更改,將來的備份是否與以前的備份兼容?是否有任何代碼需要更改? – pavium 2009-11-11 04:42:12

回答

26

我們用二元一噸不同的ID在我們的數據庫,以節省空間,因爲我們的大部分數據由這些ID的。由於它看起來並不需要節省空間(因爲它只是密碼,而不是其他大型項目),所以我沒有看到在這裏使用二進制的任何理由。我們遇到的最大問題是不斷地,令人煩惱的是,二進制數據顯示在控制檯中(每次你鍵入select *你會聽到一百萬次嗶嗶聲),並且你必須總是選擇HEX()或者插入UNHEX( ),這是一種痛苦。

最後,如果您將二進制和HEX/UNHEX混合匹配並加入此值,則可以匹配您從未打算過的記錄。

+0

+1,並被接受爲提供一些現實世界的問題和見解。謝謝! – nickf 2009-11-11 05:05:21

+0

我喜歡你使用'BINARY'來節省空間!你認爲你能幫助我在這裏走上正確的軌道嗎? http://stackoverflow.com/questions/15539540/convert-c-int-to-varbinary-and-back-again – 2013-03-23 20:10:11

2

將散列密碼存儲爲二進制而不是varchar的硬盤空間節省量可能並不重要。這個表格中您可能擁有多少用戶?乘以BINARY(20)VARCHAR(n)之間的空格差異,我認爲你會發現這不是一個顯着的節省。就個人而言,我更喜歡十六進制表示,因爲至少我可以在查詢中鍵入它,如果我在開發過程中進行臨時操作或編寫單元測試來驗證密碼相關操作。如果我碰巧在文本編輯器中加載數據轉儲等,Hex比二進制可讀性更強。我的底線是,在開發週期中,十六進制表示會更加方便。

+0

您可以隨時調用HEX(myBinaryField)以十六進制格式查看它。 – nickf 2009-11-11 04:21:37

+0

@nickf:當然可以。這將不太方便。 – Asaph 2009-11-11 04:28:50

7

這裏是我的故障:

  1. 如果使用字符串,而不是二進制,使用固定長度字段。由於哈希算法都輸出一個固定的長度,你可以節省一些空間。
  2. 由於您只進行平等比較,因此不需要索引。二進制字段沒有整理類型或字符集。
  3. BINARY列類型沒有像BLOB那樣的奇怪存儲注意事項。
  4. 每個十六進制字符代表它消耗的8位(或7位)中的4位。這意味着二進制存儲的效率是其兩倍。
  5. 最重要的:除非你在嵌入式系統中工作,否則每個字節都不要。具有字符表示可以讓您更好地進行調試。另外,每當開發人員正在處理這樣的問題時,我不得不想知道爲什麼。像這樣的每一個架構決策都有折衷,而且這似乎並不會增加項目的價值。
  6. 您隨後可以使用簡單的SQL腳本隨後轉換爲BINARY。

總之,使用固定長度的文本字段。在當前世界中計算字節沒有任何好處,特別是當易於實現更改時。

希望這會有所幫助。

0

爲什麼另起爐竈?爲什麼不使用CHAR(41)就像表'mysql.user'一樣使用?這是一個衆所周知的格式,所以任何未來的維護者都不會在你的特殊計劃中撓頭。只需注意「就像MySQL密碼」一樣,讓每個人都輕鬆一下。

2

如果你想要一個簡單的方法來存儲二進制文件在SQL ...你可以轉換爲十六進制之前。 看看這個頁面: http://kekoav.com/blog/36-computers/58-uuids-as-primary-keys-in-mysql.html

轉換爲十六進制,脫下「 - 」,並把「0X」在前面的字符串。 Mysql將理解爲一個字節內容。

實施例: INSERT INTO用戶設置的密碼= 0x1e8ef774581c102cbcfef1ab81872213

2

這是一個老問題,但我注意到沒有人提到數據驗證作爲一個優點是二進制列。具體而言,可以使用非十六進制數字(0-9,a-f)的字符將無效值存儲在CHAR(40)列中。

您仍然可以在BINARY列中插入錯誤的值(例如,如果您忘記調用UNHEX),但您永遠不必考慮從數據庫中讀取不正確解析的值。