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ログイン時に の値が直接編集されることはないため、これはまったく問題にならないばかげた問題です。 ... 長い 1 日でした。

4

2 に答える 2

1

62^55 のアドレス空間で 2^55 の衝突が発生する可能性が本当に心配な場合は、列の型を BLOB に変更するだけで済みます。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 に答える