繁体   English   中英

MySQL和php中的独特文本字段

[英]Unique text field in MySQL and php

我用盐创造了一种盐; MD5(兰特(0,10000000)); (可能有更好的方法?)

似乎没有可能在MYSQL中使文本字段唯一。 那么如何检查盐是否已用于以前的用户?

或者我应该根据当前日期/时间生成盐? 因为2个用户不可能在完全相同的时间注册正确吗?

对于盐,唯一性比长度和可预测性更重要。 你认为攻击者有盐。

通用唯一标识符(UUID)是最好的,并且有一些示例可以在php uniqueid()函数的doc页面上生成通用唯一标识符。 UUID优于随机字符串,因为它具有人类可读性和固定长度,因此您可以将其存储在varchar字段中并使用唯一索引来确保不会出现重复。

使用MD5散列时间是生成唯一值的常用方法,因为它具有固定长度并且是人类可读的。 但是,生成固定长度的随机字符串并将其自身编码为十六进制更有意义。 哈希不是为了独特而设计的,因为它们的设计不是可逆的。 使用散列函数可以保证冲突,但与SHA5相比,与MD5的冲突会更少。

盐的长度实际上只是一个因素,因为盐越长,它就越有可能是普遍独特的。

MySQL的索引在文本字段上是长度限制的,它们不会像在char / varchar字段上那样自动进入整个字段,因此没有实际的方法在文本字段上使用“唯一”键。

但是如果你存储由MySQL生成的哈希值,那么你不需要文本 - 结果是纯文本的,所以只需使用一个固定长度的字段:

mysql> select length(md5('a')), length(sha1('a'));
+------------------+-------------------+
| length(md5('a')) | length(sha1('a')) |
+------------------+-------------------+
|               32 |                40 | 
+------------------+-------------------+

然后你可以对该字段应用唯一约束。

md5()是一个破碎的算法,永远不应该触及。

rand()略有损坏,因为它基于系统时钟。

一个更好的方法是:

function generateRandomKey()
{
    return base_convert(uniqid(mt_rand(), true), 16, 36);
}

编辑:如果有更好的方法或我错了,请告诉我你这样做的方式。 我真的很感兴趣,想知道我是不安全的。

您可以使用http://php.net/manual/en/function.uniqid.php之类的东西来生成UUID。 或者时间戳也是一个好的 - 甚至可能是时间戳和IP地址或类似的。

使用用户标识和日期时间使用SHA1生成salt。

你通常不会生成盐串。 所以当你第一次生成它们时,你应该做得很好。 更长和更随机的字符串更好。

function generateSalt($length = null)
{
  if (!is_int($length) || ($length < 1)) $length = 250;
  do {
    $salt[] = chr(mt_rand(0, 255));
  } while (--$length);
  return implode('', $salt);
}

更新新密码的查询

update user set salt = :salt, password = sha1(concat(:password, :salt)) where id = :id limit 1;

您可以检查密码是否正确并同时获取用户数据。

select * from user where id = :id and password = sha1(concat(:password, salt)) limit 1;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM