1

原因:

我有一张桌子,列都适合Collatedutf8mb4_unicode_ci

CREATE TABLE IF NOT EXISTS `users` (
  `user_id` int(8) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) NOT NULL,
  `pass_word` varchar(512) NOT NULL ,
  ...etc etc...
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `email_addr` (`email_addr`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=989 ;

...包括存储密码哈希(从 生成password_hash)的列,例如$2y$14$tFpExwd2TXm43Bd20P4nkMbL1XKxwF.VCpL.FXeVRaUO3FFxGJ4Di.

但是,我发现由于该列不区分大小写,散列$2y$14$tFpExwd2tXm43Bd20P4NKmbL1XKxwF.VCpL.FxEVRaUO3FFxGJ4DI仍然允许访问。

这意味着以不区分大小写的方式存储数据可能会发生数百次冲突。不好。


问题:

现在,在进行比较时,是否有办法强制 MySQL 将pass_word列视为区分大小写的列。我想避免编辑每次出现的 PHP/SQL 查询,而是简单地将数据库表列设置为默认情况下以区分大小写的方式进行比较。

utf8mb4字符集没有给我任何_cs选项,唯一的非选项_ci似乎是utf8mb4_bin.

这么简单的问题:

  • MySQL 上的字符集和排序规则是否UTF8mb4_bin区分大小写? [是的]
  • UTF8mb4_bin我想做的事。我应该使用另一组吗?如果是,为什么?
  • password_hash将输出存储在 MySQLutf8mb4_bin列中是否有任何问题?
  • 这种方法是否方便地回避了编辑每个登录查询的查询 SQL 的需要?我可以更改列类型然后继续吗?

编辑

正如 nj_ 所详述的,这是一个愚蠢的问题,根本不是问题,因为pass_word登录时永远不会直接编辑 的值。......这是漫长的一天。

4

2 回答 2

1

如果您真的担心 62^55 地址空间中潜在的 2^55 冲突,您可以简单地将列类型更改为 BLOB,它始终区分大小写。

CREATE TABLE IF NOT EXISTS `users` (
  `user_id` int(8) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) NOT NULL,
  `pass_word` BLOB NOT NULL ,
  ...etc etc...
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `email_addr` (`email_addr`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=989 ;

例子:

INSERT INTO `users` (..., `pass_word`) VALUES (..., 'AbC');

SELECT * FROM `users` WHERE `pass_word` = 'AbC' LIMIT 0,1000;-> 1 次命中

SELECT * FROM `users` WHERE `pass_word` = 'abc' LIMIT 0,1000;-> 0 次点击

于 2016-03-30T16:20:10.413 回答
1

在这种情况下区分大小写是没有问题的,因为无论如何您都无法直接使用 SQL 验证密码。无法在数据库中搜索正确加盐的密码哈希。仅按用户名搜索并从数据库中提取存储的哈希:

$sql= 'SELECT * FROM users WHERE username = ?';
$db->prepare($sql);
$db->bind_param('s', $_POST['username']);

之后,您可以从行中提取哈希,并使用 password_verify() 函数检查输入的密码与找到的哈希:

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
于 2016-03-30T17:24:51.160 回答