電子メール確認コードのベスト プラクティス
-
19-09-2019 - |
質問
ユーザーのサインアップを必要とする PHP Web サイトを作成しているのですが、「電子メール確認」コードのベスト プラクティスについて疑問に思っています。
新規ユーザーは自分の電子メール アドレスを確認する必要があります。これを行うには、コードを生成し、それを電子メールでユーザーに送信します。これにより、ユーザーはそのコードを使用してアカウントをアクティブ化できます。このキーをデータベースに保存するのではなく、次のような便利な回避策を使用しています。コードは次の結果です。
md5("xxxxxxxxx".$username."xxxxxxxxxxx".$timestamp."xxxxxxxxx");
ここで、$timestamp はユーザーの作成時間を指します。全体的にはこれに非常に満足していましたが、これで十分安全なのかと考えるようになりました。そして、衝突の可能性についてはどうでしょうか?また、パスワードリセットなどのためのコードを生成する必要もあります。同様の方法を使用した場合、衝突により、あるユーザーが別のユーザーのパスワードを誤ってリセットしてしまう可能性があります。それはダメだ。
では、これらのことをどのように行うのでしょうか?私が考えたのは、次の形式の表です。
codePK (int, a-I), userID (int), type (int), code (varchar 32), date (timestamp)
ここで、「タイプ」は 1、2、または 3 で、「アクティベーション」、「電子メールの変更」、または「パスワードのリセット」を意味します。これは良い方法でしょうか?もっと良い方法はありますか?
上記と同様の方法を使用して、cron ジョブを使用せずに 2 日以上経過したものを自動的に削除できますか?私のホスト (nearlyfreespeech.net) はそれらをサポートしていません。可能であれば、wget が物事を削除するスクリプトである外部ホスト上で cron ジョブを実行することは避けたいと思います。それは単に面倒なためです =P。
ありがとう!
マラ
アップデート:
明確にするために:このタスクを安全かつ安全に実行する唯一の方法はデータベースを使用することですが、これは元の関数が避けようとしていたものであることに気付きました。私の質問は、テーブル (または複数のテーブル?) をどのように構造化すべきかということです。誰かが codePK を廃止してコードを PK にするだけだと提案しました。つまり、私の質問は次のとおりです。これはあなたがやることですか?
解決
このような種類のトリックが必要な場合は、通常、あなたが挙げた 2 つの理由のいずれかです。
- ユーザーに送信される確認メールに使用されるキーとして
- パスワードリセットリンクに使用されるキーとして
もちろん、このような構造の使用を検討する機会は他にもたくさんあるでしょう。
まず第一に、あなただけが知っている隠された塩を常に使用する必要があります。このソルトはユーザーごとに異なる必要があることに注意してください。塩は、たとえば次のように計算できます。 sha256(something random)
. 。このソルトは、ユーザー名とパスワード (ソルトでハッシュ化されたもの) とともにデータベースに保存する必要があります。
パスワード リセット リンクを送信するときに行うことは、別のソルトを作成することです (ソルトでハッシュされたものへのアクセスをユーザーに与えないでください)。彼は自分のパスワードを知っているため、ブルートフォースを使用してあなたのソルトを解明できる可能性があります)。もう 1 つのソルトは、基本的にはランダムな文字列のハッシュにすぎません (長さが問題であると述べたので、ここでは md5 を使用することをお勧めします)。これをデータベースに保存します。
多くの場合、users テーブルに追加の列を追加するだけで済みます。ただし、これにはいくつかの問題もあります。主に、パスワードがリセットされるか、ユーザーがアクティブ化されると、データベースからキーを削除することになり、その結果、ほとんどの行が NULL 値を持つことになり、別の問題が発生します。 。
これは本質的に次のとおりです。
- ユーザー固有のソルト (そして おそらく世界的な秘密の塩です)。
- タイムスタンプなどの多数のランダムまたは疑似ランダム ソースをハッシュしてキーを生成します。
mt_rand()
本当にランダムなものが必要な場合は、random.org を使用することもできます。 - パスワード リセット キーやアクティベーション キーなど、ユーザーがアクセスできるものをハッシュするために、グローバル ソルトやユーザーに固有のソルトを決して使用しないでください。
私は決してセキュリティの専門家ではないので、おそらく多くのことを忘れており、いくつかの非常に悪い習慣について言及した可能性があることに注意してください。私の5セントだけです ;-)
他のヒント
なぜ認証キーのための基礎として、ユーザのデータのいずれかを使用できますか?
//www.php:私はあなたがなぜ単にランダムキー(おそらくmd5'ed <のhref = "HTTPで追加のレコードを追加しないで、データベース内のデアクティブにデータを保存していると推定します。マニュアル/ネット/ EN / function.uniqid.php」のrel = "nofollowをnoreferrer"> uniqid のいくつかの追加操作に)し、そのに対してチェック?
これは、右のあなたがインターネット上であなたの方法を公開し時点までに十分なセキュリティで保護されました!あなたは良いアイデアではないあいまいで、セキュリティに頼っていたためです。
あなただけに知られている秘密鍵を組み込んだ、理想的には鍵付きハッシュ関数やMACのいくつかの並べ替えを使用するべきである。
なぜコードフィールド一意のインデックスを作ってみませんか?だから、collsisionsがないんでしょうか?
また、ユーザー入力からハッシュを作成し、データベースハッシュ(電子メールの確認、パスワードなどリセット)にそれを一致させる必要がない場合 - あなたは次のように、ハッシュ本体にランダムな文字列を追加することができます
md5('xxx'.$username.'xxx'.time().'xxx'.rand())
なぜ、それによって衝突を持つ任意の問題を排除し、ユーザー名との自分のコードを入力するようユーザーに依頼しませんか?それでも彼らは、電子メールから取得したいキーを求めているとして、あなたは何のセキュリティワイズを失うことはありませんが、あなたは彼らが他のユーザのパスワードをリセットすることができることを停止すると思います。