标签:intervals datetime mysql php group-by
给定尝试次数后,我试图阻止用户访问.在停止阅读之前,因为已经有人问过这个问题,所以让我解释一下我的情况(如果已经问过,请指出重复的问题).
我想要什么
我要实现的是每个时间间隔的阻塞时间.因此,如果有:
5分钟内尝试3次以上:用户阻止5分钟
10分钟内尝试5次以上:用户阻止10分钟
15分钟内尝试10次以上:用户15分钟内屏蔽
这考虑了尝试登录的电子邮件以及来自哪个IP的电子邮件.因此,如果用户尝试从其他IP访问相同的电子邮件帐户,则可以这样做(并且如果同一IP尝试了另一个用户,则也可以这样做).
拜托,我知道这不是安全性问题上的最佳解决方案-也许-但是解决该问题也将对我的MySQL学习有所帮助,因此,我想跳过安全性建议,而仅着重于如何在MySQL查询中实现这一点.可能.
我有的
我的数据库中有一个登录尝试表:
CREATE TABLE IF NOT EXISTS `er_login_attempts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`target_mail` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`attempt_date` datetime NOT NULL,
`attempt_success` tinyint(4) DEFAULT '1',
`ip_from` varchar(36) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
因此,我已经注册了尝试登录的日期.每次尝试都会创建一个新的寄存器.由于间隔时间不同,因此以这种方式执行此操作(因此,我无法使用“尝试”字段,因为我不知道自上次尝试以来已经过去了多少时间).
如果尝试最终成功,则此条目的“ attempt_success”将设置为1.如果未成功,则将其设置为0.
我尝试过的
我试图做的是编写一个MySQL查询,该查询返回每个时间间隔的错误尝试次数.然后,我将在PHP中使用它,并做一些IF检查每个间隔是否已达到限制.
因此,我尝试过的查询(请不要笑):
SELECT count(cinc.id) AS cinc_minuts, count(deu.id) AS deu_minuts, count(quinze.id) AS quinze_minuts
FROM er_login_attempts cinc, er_login_attempts deu, er_login_attempts quinze
WHERE 'mail@mail.com' IN (cinc.target_mail, deu.target_mail, quinze.target_mail)
AND '1.11.11.111' IN (cinc.ip_from, deu.ip_from, quinze.ip_from)
AND cinc.attempt_date BETWEEN MAX(cinc.attempt_date) AND DATE_SUB(MAX(cinc.attempt_date), INTERVAL 5 minutes)
AND deu.attempt_date BETWEEN MAX(deu.attempt_date) AND DATE_SUB(MAX(deu.attempt_date), INTERVAL 10 minutes)
AND quinze.attempt_date BETWEEN MAX(quinze.attempt_date) AND DATE_SUB(MAX(quinze.attempt_date), INTERVAL 5 minutes)
但!我收到“分组依据”错误.我试图添加一个“分组依据”表达式以按target_mail,按IP,按INTERVALS对其进行分组,但我一次又一次遇到相同的错误.
但是,正如您所看到的,该查询没有考虑已成功进行登录尝试,并且如果进行了成功尝试,则所有较旧的错误尝试都将被忽略-但不会被删除,这真是太好了.
有了这一切
希望您能对我要实现的目标有所了解.再一次,如果有人问过我,我要感谢那些为我指出正确方向的人,如果是这样,则对不起,我重复了这个问题.
如果您需要更多信息,或者我跳过了一些重要的事情,请告诉我,我将尝试写下缺少的信息.
感谢大家的宝贵时间!
解决方法:
首先要注意的是,不要将IP地址存储为字符串-它们是使人类可以读取大量数字的便捷方式.但是,如果您要开始对该地址进行进一步处理(扫描子网中的登录,进行特定国家/地区的验证…),则需要使用IP地址.
SELECT
SUM(IF(secs_ago<=300, 1, 0)) as attempts_in_last_5,
SUM(IF(secs_ago<=600, 1, 0)) as attempts_in_last_10,
SUM(IF(secs_ago<=900, 1, 0)) as attempts_in_last_15
FROM
(
SELECT
UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(attempt_date) AS secs_ago
FROM er_login_attempts
WHERE target_email='mail@mail.com'
AND INET_ATON('1.11.11.111')=ip_from
AND attempt_date>NOW() - INTERVAL 15 MINUTES
) ilv;
….并且您的主键对于您描述的目的几乎没有用-但是您确实需要在try_date,target_email和ip_from上建立索引(很可能按此顺序).
这需要一些工作来适应阻塞时间-最简单的解决方案是添加第二个表.
标签:intervals,datetime,mysql,php,group-by 来源: https://codeday.me/bug/20191121/2052124.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。