3

ユーザーのログインをチェックする次のような SQL ステートメントがあるとします。

SELECT * FROM users 
WHERE username='test@example.com', password='abc123', expire_date>=NOW();

各条件を独自のクエリに分割して個別にテストすることなく、どの WHERE 条件が失敗したかを具体的に判断する SQL の方法はありますか?

この特定の例では、開発者はログイン試行が失敗した理由をユーザーに正確に伝えることができます。

私の目的のために、私は PHP/MySQL を使用しています。

4

5 に答える 5

6

できることの 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'
于 2009-09-11T17:17:46.297 に答える
4

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: これはあなたの質問から少し離れていますが、パスワードを平文で保存しないことを強くお勧めします。ソルトされたパスワードのハッシュ ダイジェストを保存します。パスワードソルトはレインボーテーブル攻撃に対してどのように役立ちますか? を参照してください。

于 2009-09-11T17:25:00.910 に答える
1

いいえ、where 句はブロックとして適用され、さまざまな手法が使用されるため、すべての行をスキャンする必要はありません。また、どの行が目的の行であるかをどのように知ることができますか?

さらに、ログイン試行が失敗した理由について、ユーザーにあまり多くを伝えたくないでしょう。言いすぎると、アカウント マイニングやパスワード攻撃などのエクスプロイトが可能になります。

編集本当にこれをユーザーに表示したい場合は、ロジックをさまざまな部分に分割します。

  1. ID の検証
    アクション: データベースから対応するユーザー行をフェッチします
    結果:
    • そのような行が存在しない場合 => 無効なアカウント
    • 行が返された場合は、ステップ 2 に進みます。
  2. 資格証明の検証
    アクション: 保管された資格証明 (パスワード、パスワードのハッシュ、または暗号化されたパスワード) を、資格証明が保管されているのと同じ方法で処理された提供されたパスワードと比較してチェックします。
    結果:
    • 一致なし => 無効なパスワード/資格情報
    • 一致 => ログイン試行の成功
  3. ログイン ユーザー
    アクション: セッションなどにデータを追加します。
于 2009-09-11T17:20:02.970 に答える
0

where句の部分を「AND」で区切るだけでよいでしょう。

SELECT * FROM users 
WHERE username='test@example.com'
   And password='abc123'
   And expire_date>=NOW();
于 2009-09-11T17:24:44.623 に答える
0

これが私が思いついたものです:

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'

このようにして、コード内でエラー メッセージを検出し、必要に応じて表示することができます。

注:コード例でセキュリティ上の問題を挙げている皆さん、ご心配ありがとうございます。ただし、これは実際の製品コードではありません。これは、私が持っていた質問を示すための単純な例です。パスワードを平文で保存してはならないこと、ログインに失敗した理由をユーザーに詳しく教えてはならないことは明らかです。

于 2009-09-11T17:30:48.997 に答える