WHEREステートメントのどの部分が失敗したかを判断する
-
05-07-2019 - |
質問
ユーザーログインをチェックする次のようなSQLステートメントがあるとします。
SELECT * FROM users
WHERE username='test@example.com', password='abc123', expire_date>=NOW();
各条件を独自のクエリに分けて個別にテストすることなく、どのWHERE条件が失敗するかを具体的に判断する方法はSQLにありますか?
この特定の例では、開発者がユーザーにログイン試行が失敗した理由を正確に伝えることができます。
私の目的では、PHP / MySQLを使用しています。
解決 5
ここに私が思いついたものがあります:
SELECT
IF(mem_username='test@example.com','true','Error: Bad Username') AS mem_username,
IF(mem_password ='abc123','true','Error: Bad Password') AS mem_password'
FROM MEMBERS
WHERE mem_username='test@example.com' AND mem_password='abc123'
これにより、エラーメッセージのコードを検出し、必要に応じて表示できます。
注: サンプルコードでセキュリティ上の懸念を挙げているすべての人に、懸念をお寄せいただきありがとうございます。ただし、これは実際の製品コードではなく、これは単に私が持っていた疑問を示すための単純な例です。パスワードを平文で保存するべきではなく、ログインが失敗する理由についてユーザーに具体的な情報を与えてはならないことは明らかです。
他のヒント
さて、できることの1つは、ユーザー名にのみ一致するようにクエリを変更することです。次に、コードでパスワードと有効期限を確認し、適切なエラーを返します。
また、クエリの例が単純化されることを願っています。確かに、パスワードをソルト/暗号化/ハッシュする必要があります。また、特定の期間内に失敗する試行回数などを制限するものを含める必要があります...
(探している結果ではなく)実際の質問に関しては、where句からその情報を取得する方法はありません。最も近い方法は次のようなものです:
SELECT *,
CASE WHEN Password = 'asdf' THEN 1 ELSE 0 END AS IsPasswordMatch,
CASE WHEN Expiration >= NOW() THEN 1 ELSE 0 END AS IsActiveAccount
FROM Users
WHERE Username = 'user'
MySQLでは、選択リストにブール式を含めることができます。ブール式は、真の場合は整数1、偽の場合は整数0に評価されます。
SELECT password = 'abc123' AS is_authenticated,
expire_date >= NOW() AS is_not_expired
FROM users
WHERE username='test@example.com';
注:他のブランドのRDBMSで機能するクエリを作成する必要がある場合、このブール式の使用は非標準であることに注意してください。他の人が投稿した CASE
構文を使用します。
PS:これはあなたの質問の接線ですが、パスワードを平文で保存しないことをお勧めします。ソルトされたパスワードのハッシュダイジェストを保存します。 パスワードソルトがレインボーテーブル攻撃に対してどのように役立つか
をご覧ください。いいえ、where節はブロックとして適用され、すべての行をスキャンする必要がないようにさまざまな手法が使用されます。また、どの行が目的の行であったかをどのように確認しますか?
さらに、ログイン試行が失敗した理由をユーザーに伝えたくはないでしょう。言いすぎると、アカウントマイニングやパスワード攻撃などの悪用が可能になります。
編集本当にこれをユーザーに表示したい場合は、ロジックを異なる部分に分割します:
- IDの検証
処置:データベースから対応するユーザー行をフェッチします
結果:- そのような行が存在しない場合=>無効なアカウント
- 行が返された場合は、手順2に進みます。
- 資格情報の検証
アクション:保管された資格情報(パスワード、パスワードのハッシュ、または暗号化されたパスワード)を、資格情報の保管と同じ方法で処理された指定のパスワードと照合してください。
結果:- 一致なし= gt;無効なパスワード/資格情報
- Match =>ログイン試行の成功
- ログインユーザー
アクション:セッションなどにデータを追加します。
おそらく、「AND」でwhere句の部分を分離する必要があるだけです
SELECT * FROM users
WHERE username='test@example.com'
And password='abc123'
And expire_date>=NOW();