我有一个PHP应用程序,将所有账户存储在同一个表中,无论它们是否处于活动状态。该表有一列名为"active",其值可以是NULL(表示账户处于活动状态),或包含MD5哈希值(表示账户不活动)。
根据在MySQL中高效存储MD5哈希的最佳实践,如果该列始终包含MD5哈希而从不为NULL,则BINARY(16)是首选,CHAR(32)是次佳选择。由于我的大多数账户都处于活动状态,因此大多数列值将为NULL,那么我是否更好地使用不同的数据类型,例如VARCHAR(32)?
我有一个PHP应用程序,将所有账户存储在同一个表中,无论它们是否处于活动状态。该表有一列名为"active",其值可以是NULL(表示账户处于活动状态),或包含MD5哈希值(表示账户不活动)。
根据在MySQL中高效存储MD5哈希的最佳实践,如果该列始终包含MD5哈希而从不为NULL,则BINARY(16)是首选,CHAR(32)是次佳选择。由于我的大多数账户都处于活动状态,因此大多数列值将为NULL,那么我是否更好地使用不同的数据类型,例如VARCHAR(32)?
使用 VARCHAR 没有意义。MD5 哈希值始终为 128 位,因此 CHAR(32) 保存十六进制数字的字符串,或者 BINARY(16) 保存解码十六进制数字后的字节字符串。
使用 NULL 与数据类型选择无关。MySQL 可以在需要字符串(CHAR 或 VARCHAR)时存储 NULL。但是实际上,在 InnoDB 默认的行格式中,MySQL 不会存储任何 NULL,对于列为空的情况,不会存储任何内容。
参考文献:http://dev.mysql.com/doc/internals/en/innodb-field-contents.html
关于 NULL 的一些注意事项:
对于第三行,我在 FIELD2 和 FIELD3 中插入了 NULL。因此,在“字段起始偏移量”中,这些字段的最高位为 1(值为 94 十六进制),而不是 0(值为 14 十六进制)。由于 NULL 不占用空间,所以该行更短。
(强调是本人添加)
注:更新日期:2019年5月11日
理想情况下,您不应再使用MD5来哈希密码。
PHP手册已经添加了一个安全的密码哈希部分,大约在4-5年前,其中解释了password_hash()
和password_verify()
以及为什么不适合使用MD5 / SHA1..
请记住,由于大多数关系型数据库管理系统(RDMS)都设计成可以提供非常稳定的时间,因此当password
列在WHERE
子句中时,大多数RDMS会缓存数据在内存中或索引化数据,这使得定时攻击变得非常可能。
在“伪”PHP代码中,结合SQL使用password_verify()
的安全方法是完全可行的。
$row = prepare("SELECT password FROM users WHERE username = :username").execute().fetch();
if (password_verify($_POST['password'], $row->password)) {
// password correct
} else {
// password incorrect..
}
<?php
md5 ( "password", true ); // true returns the binary what is 16 bytes long MySQl BINARY(16)
?>
VARCHAR(32)
更好。 - Sumit Bijvani