-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSimpleAntiBruteForce.php
83 lines (69 loc) · 2.48 KB
/
SimpleAntiBruteForce.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?php
namespace SimpleAntiBruteForce;
use App\Entities\Database;
/**
*
* SimpleAntiBruteForce - https://github.com/gatienfrenchdev/SimpleAntiBruteForce
*
* Small library to manage brute force attempts on a PHP form.
* Didn't find a library that offered a correct and simple system.
*
*
* To use it, you only need to create a MySQL table on your project following this data model:
* user_failed_logins(id: int, email: varchar, attempted_at:int, ip_adress:varchar)
*
* Then call the `::isAuthorized()` method before verifying the entered password.
*
* And call the `::addFailedAttempt()` method when a connection fails to remember it.
*
* For any questions, contact me by email.
*
* @author GatienFrenchDev <[email protected]>
* @license MIT
* @version 1.0
* @copyright Copyright (c) 2024 GatienDev
*
*/
class SimpleAntiBruteForce
{
private static int $MAX_FAILED_ATTEMPT = 10;
private static int $INTERVAL_IN_S = 300;
/**
* To check if the IP is allowed to connect.
* @param string $ip_adress The IP address of the user.
* @param string $email The email of the user.
* @return bool `true` if the user is allowed to connect, `false` otherwise.
*/
static function isAuthorized(string $ip_adress, string $email): bool
{
$mysqli = Database::getInstance();
$timestamp_max = time() - self::$INTERVAL_IN_S;
$stmt = $mysqli->prepare("SELECT COUNT(id) as nb FROM user_failed_logins WHERE email = ? AND ip_adress = ? AND attempted_at > ?");
$stmt->bind_param("ssi", $email, $ip_adress, $timestamp_max);
$stmt->execute();
$res = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
$stmt->close();
return $res[0]["nb"] < self::$MAX_FAILED_ATTEMPT;
}
/**
* To add a failed attempt in the database.
* @param string $ip_adress The IP address of the user.
* @param string $email The email of the user.
* @return void
*/
static function addFailedAttempt(string $ip_adress, string $email): void
{
$mysqli = Database::getInstance();
$current_time = time();
// add a new record in the db
$stmt = $mysqli->prepare("INSERT INTO user_failed_logins (email, attempted_at, ip_adress) VALUES (?, ?, ?)");
$stmt->bind_param("sis", $email, $current_time, $ip_adress);
$stmt->execute();
// clean the db by removing expired attempt
$min_expired_timestamp = time() - 2 * self::$INTERVAL_IN_S;
$stmt = $mysqli->prepare("DELETE FROM user_failed_logins WHERE attempted_at < ?");
$stmt->bind_param("i", $min_expired_timestamp);
$stmt->execute();
$stmt->close();
}
}