我正在尝试构建一个MySQL
查询(或PHP
脚本),以识别与其他人共享web登录凭据的用户。我想避免强迫用户明确注册他们的设备(就像银行一样),因为我想尽量减少给真正用户带来的不便。我意识到没有办法完全消除假阳性或假阴性,但我想尽我所能做到最好。
在登录时,服务器将ip address
、user id
和browser fingerprint
(fingerprintjs2)存储到数据库中。(指纹是一个半唯一的浏览器值)。
如果每个用户只使用一个ip
,这将是轻而易举的事——我只使用SELECT
所有从多个ip登录网站的用户。当然,事实并非如此。在现实世界中,用户可以从多个连接(例如,工作、家庭、电话)登录,在dynamic ips
的情况下,地址本身可以更改。
大多数用户不会有超过5个不同的连接(也有例外,但并不多)。我承认(可能)没有办法确定一个人是否从5个不同的连接登录,或者是否有5个人分别从一个连接登录。
只要我的查询只捕获从登录超过5个连接的用户,"每个用户多个连接"的问题就不存在了。
现在我必须面对dynamic ips
的用户问题。
据我所知,大多数提供动态连接的ISPs
只会更改最后一组数字(我希望得到一些关于这方面的确认或统计数据)。
如果我的查询认为"连接"是前3组ip
数字,那么对于只更改最后一组数字的ISPs
用户,问题就解决了。
下面是我编写的一个简单的MySQL
查询。它按用户名对不同的ips
(没有最后一组数字)进行分组,并显示与其中5个以上相关的用户名:
SELECT
GROUP_CONCAT(DISTINCT ip SEPARATOR '/') AS ips,
username,
COUNT(DISTINCT ip) AS n_ips
FROM
(
SELECT DISTINCT user_id, SUBSTRING_INDEX(ip_address,'.',3) AS ip
FROM
ip_logins
WHERE
login_date > DATE_SUB(NOW(), INTERVAL 7 DAY )
) AS weekips
JOIN users AS u ON (
u.id = weekips.user_id
)
GROUP BY
username
HAVING
COUNT(n_ips) > 5
ORDER BY
n_ips DESC
我打算处理"完全"dynamic ips
(其中任何数字都可以更改)的方法是将共享同一browser fingerprint
的所有登录计数为单个"连接"。我的理由是,如果一个用户使用相同的browser fingerprint
从多个ip登录,那么所有这些登录都可能来自一个使用"完全"dynamic ip
的个人。这并不能完全解决问题,因为它无法考虑使用多个浏览器的用户(因为浏览器指纹会有所不同)。
我可以使用cookie代替browser fingerprint
,但这些cookie可以被删除或禁用。
我很乐意为我的策略提供一些意见,并提供一些如何改进它的技巧。如果已经有这样的开源实现(在PHP
中),我想知道;再发明轮子也没用。
为什么不简单地开始,比如:检测用户何时同时从两个或多个IP访问网站,阈值为<请求间隔30秒。这应该已经抓住了很多坏人。
id account_id ip_address time page
1 1 1.1.1.1 00:00:00 /weather/amsterdam/today <-- multiple IPs
2 1 2.2.2.2 00:00:05 /weather/london/yesterday <-- on the same
3 1 3.3.3.3 00:00:06 /weather/brussels/today <-- account
4 1 4.4.4.4 02:02:02 /weather/paris/tomorrow