Domanda

Diciamo che ho un'istruzione SQL come questa che controlla un accesso utente:

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

Esiste un modo in SQL per determinare in modo specifico quali condizioni WHERE falliscono, senza dover separare ciascuna condizione nella propria query e testare singolarmente?

In questo esempio specifico consentirebbe allo sviluppatore di comunicare agli utenti esattamente il motivo per cui il loro tentativo di accesso non è riuscito.

Per i miei scopi sto usando PHP / MySQL.

È stato utile?

Soluzione 5

Ecco cosa mi è venuto in mente:

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'

In questo modo posso rilevare nel codice i messaggi di errore e quindi visualizzarli come necessario.

NOTA : A tutti voi che citate problemi di sicurezza con il codice di esempio, grazie per la vostra preoccupazione. Tuttavia, questo non è un vero codice di produzione, è stato semplicemente un semplice esempio per dimostrare la domanda che avevo. È abbastanza ovvio che non dovresti archiviare le password in chiaro e che non dovresti fornire agli utenti specifiche sul perché l'accesso non riesce.

Altri suggerimenti

Bene, una cosa che potresti fare è cambiare la tua query in modo che corrisponda solo al nome utente. Quindi nel codice controlli la password e la data di scadenza, restituendo gli errori appropriati.

Inoltre, spero che la tua query di esempio sia una semplificazione; Certamente dovresti salare / crittografare / eseguire l'hashing delle tue password e dovresti includere qualcosa che limiti il ??numero di tentativi falliti entro un certo periodo di tempo, ecc ...

Per quanto riguarda la tua vera domanda (al contrario dei risultati che stai cercando), non c'è modo di ottenere tali informazioni dalla clausola where. Il più vicino che potresti fare sarebbe qualcosa di simile:

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'

In MySQL è possibile inserire espressioni booleane nell'elenco di selezione. Le espressioni booleane vengono valutate sull'intero 1 se vero o sull'intero 0 quando falso.

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

nota: se devi scrivere una query che funziona su altri marchi di RDBMS, tieni presente che questo uso di espressioni booleane non è standard. Usa la sintassi CASE che altre persone hanno pubblicato.

PS: questa è una tangente alla tua domanda, ma ti esorto a non memorizzare le password in chiaro. Memorizza un digest hash della password salata. Vedi In che modo la password salt aiuta contro un attacco da tavolo arcobaleno?

No, la clausola where viene applicata come blocco e vengono utilizzate varie tecniche in modo che non tutte le righe debbano essere sottoposte a scansione. Inoltre, come faresti a sapere quale riga era quella desiderata?

Inoltre, probabilmente non vuoi dire troppo all'utente del motivo per cui un tentativo di accesso non è riuscito. Dire troppo consente exploit come il mining degli account e gli attacchi con password.

modifica Se vuoi davvero mostrarlo al tuo utente, allora dividi la tua logica in parti diverse:

  1. Convalida identità
    Azione: recuperare la riga utente corrispondente dal database
    Risultato:
    • Se non esiste tale riga = > account non valido
    • Se viene restituita la riga, continuare con il passaggio 2.
  2. Convalida credenziali
    Azione: verificare le credenziali archiviate (password, hash della password o password crittografata) rispetto alla password fornita trattata nello stesso modo in cui le credenziali vengono archiviate.
    Risultato:
    • Nessuna corrispondenza = > Password / credenziali non valide
    • Match = > Tentativo di accesso riuscito
  3. Accedi utente
    Azione: aggiungere dati alla sessione ecc.

Probabilmente devi solo separare le parti della clausola where con 'AND'

SELECT * FROM users 
WHERE username='test@example.com'
   And password='abc123'
   And expire_date>=NOW();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top