确定 WHERE 语句的哪一部分失败
-
05-07-2019 - |
题
假设我有一个像这样的 SQL 语句来检查用户登录:
SELECT * FROM users
WHERE username='test@example.com', password='abc123', expire_date>=NOW();
SQL 中有没有一种方法可以专门确定哪些 WHERE 条件失败,而不必将每个条件分离到自己的查询中并单独进行测试?
在这个特定的示例中,它将允许开发人员准确地告诉用户他们尝试登录失败的原因。
出于我的目的,我使用 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'
这样我可以在代码中检测错误消息,然后根据需要显示它们。
注意: 对于所有引用示例代码的安全问题,感谢您的关注。但是,这不是真正的生产代码,这只是一个简单的例子来证明我的问题。很明显,您不应该以明文形式存储密码,并且您不应该向用户说明登录失败的原因。
其他提示
嗯,您可以做的一件事是更改您的查询,以便它只匹配用户名。然后在代码中检查密码和到期日期,返回适当的错误。
另外,我希望您的示例查询是一种简化;当然你应该对你的密码进行腌制/加密/散列,你应该包括一些限制在特定时间范围内失败尝试次数的东西,等等......
就您的实际问题而言(与您正在寻找的结果相反),没有办法从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中,您可以将布尔表达式放在选择列表中。布尔表达式在为true时计算为整数1,在为false时计算为整数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-子句作为一个块应用,并且使用了各种技术,因此不必扫描所有行。另外,您如何知道哪一行是所需的行?
此外,您可能不想告诉用户太多有关登录尝试失败的原因。说得太多会导致帐户挖掘和密码攻击等漏洞。
编辑 如果您确实想向用户显示此内容,请将您的逻辑分成不同的部分:
- 验证身份
行动:从数据库中取出对应的用户行
结果:- 如果不存在这样的行=>帐户无效
- 如果返回行,请继续步骤 2。
- 验证凭证
行动:根据以与存储凭证相同的方式处理的提供的密码,检查存储的凭证(密码、密码散列或加密密码)。
结果:- 不匹配 => 密码/凭证无效
- 匹配 => 登录尝试成功
- 登录用户
行动:将数据添加到会话等。
您可能只需要将where子句的部分与'AND'
分开SELECT * FROM users
WHERE username='test@example.com'
And password='abc123'
And expire_date>=NOW();