Pergunta

Vamos dizer que eu tenho uma instrução SQL como esta que verifica um login de usuário:

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

Existe uma maneira no SQL para determinar especificamente quais condições WHERE falhar, sem ter que separar cada condição em sua própria consulta e teste individualmente?

Neste exemplo específico seria permitir que o desenvolvedor para informar aos usuários exatamente a razão pela qual a sua tentativa de login falhou.

Para os meus propósitos que estou usando PHP / MySQL.

Foi útil?

Solução 5

Aqui está o que eu vim com:

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'

Esta maneira que eu possa detectar no código para mensagens de erro e, em seguida, exibi-los quando necessário.

NOTA: A todos vós citando preocupações de segurança com o código de exemplo, muito obrigado pela sua preocupação. No entanto, este não é o código de produção real, isso era simplesmente um exemplo simples para demonstrar a pergunta que eu tinha. É bastante óbvio que você não deve armazenar senhas em texto claro, e que você não deve dar aos usuários detalhes sobre o porquê de login falhar.

Outras dicas

Bem, uma coisa que você poderia fazer é alterar a sua consulta para que ele corresponde apenas no nome do usuário. Em seguida, o código que você verificar a senha ea data de validade, retornando erros apropriados.

Além disso, eu espero que o seu exemplo de consulta é uma simplificação; Certamente você deve ser salga / criptografar / hash de suas senhas, e você deve incluir algo que limita o número de tentativas falhadas dentro de um determinado período de tempo, etc ...

Quanto a sua pergunta real (em oposição aos resultados que você está procurando), não há uma maneira de obter essa informação a partir da cláusula WHERE. O mais próximo que você poderia fazer seria algo como:

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'

No MySQL você pode colocar expressões booleanas na lista de seleção. expressões booleanas avaliar para o número inteiro 1, quando verdadeiro, ou o número inteiro 0, quando falsa.

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

Nota: Se você precisa escrever uma consulta que funciona em outras marcas de RDBMS, tenha em mente que este uso de expressões booleanas é fora do padrão. Use a sintaxe CASE que outras pessoas postaram.

PS: Esta é uma tangente de sua pergunta, mas peço-lhe para não armazenar senhas em texto simples. Armazenar um hash digerir da senha salgada. Consulte Como é que ajuda sal senha contra um ataque tabela arco-íris?

Não, o onde cláusula é aplicada como um bloco, e várias técnicas são usadas de modo que nem todas as linhas têm de ser digitalizado. Além disso, como você sabe qual linha foi o que foi desejado?

Além disso, você provavelmente não quer dizer que o usuário muito sobre por que uma tentativa de login falhou. Dizer muito permite façanhas como ataques conta de mineração e senha.

Editar Se você realmente quer mostrar isso ao seu usuário, em seguida, dividir sua lógica em diferentes partes:

  1. identidade Validar
    Ação: Retorna a linha do usuário correspondente do banco de dados
    Resultado:
    • Se não existirem linha => conta inválido
    • Se linha é retornada, continue para o passo 2.
  2. Validar credencial
    Ação: Verifique a credencial armazenada (senha, hash da senha ou senha criptografada) contra a senha fornecida tratados da mesma forma a credencial é armazenada.
    Resultado:
    • No match => Senha inválida / credencial
    • Jogo => tentativa de login bem-sucedida
  3. user Entrada
    Ação:. Adicionar dados a sessão etc

Você provavelmente só precisa separar as partes da cláusula WHERE com 'E'

SELECT * FROM users 
WHERE username='test@example.com'
   And password='abc123'
   And expire_date>=NOW();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top