added registration

This commit is contained in:
Zdenek Borovec 2024-05-05 20:25:40 +02:00
parent 3f34b7f650
commit 081b26af60
4 changed files with 232 additions and 15 deletions

View file

@ -7,16 +7,14 @@ class User
{ {
public $user_id; public $user_id;
public $user_name; public $user_name;
public $email;
public $permissions; public $permissions;
/** /**
* Constructor for the User. * Constructor for the User.
*/ */
public function __construct($userId, $username, $email, $permissions) { public function __construct($userId, $username, $permissions) {
$this->user_id = $userId; $this->user_id = $userId;
$this->user_name = $username; $this->user_name = $username;
$this->email = $email;
$this->permissions = $permissions; $this->permissions = $permissions;
} }
} }

View file

@ -18,7 +18,6 @@ function attempt_login($conn, $username, $password) {
global $passwordOld; global $passwordOld;
global $usernameErr; global $usernameErr;
global $passwordErr; global $passwordErr;
global $conn;
// Check DB connection // Check DB connection
if($conn == null){ if($conn == null){
@ -38,9 +37,9 @@ function attempt_login($conn, $username, $password) {
// Check if both fields are filled, if not, set appropriate error messages. // Check if both fields are filled, if not, set appropriate error messages.
if (empty($username)) if (empty($username))
$usernameErr = "Please enter your email"; $usernameErr = "Please enter your username.";
if (empty($password)) if (empty($password))
$passwordErr = "Please enter your password"; $passwordErr = "Please enter your password.";
// If either of the fields were empty, // If either of the fields were empty,
// set old values for prefill and return. // set old values for prefill and return.
@ -51,7 +50,7 @@ function attempt_login($conn, $username, $password) {
} }
// Prepare and bind the sql statement // Prepare and bind the sql statement
$stmt = $conn->prepare("SELECT user_id, email, password, $stmt = $conn->prepare("SELECT user_id, password,
created_at, permissions FROM users WHERE username = :username;"); created_at, permissions FROM users WHERE username = :username;");
$stmt->bindParam(":username", $username); $stmt->bindParam(":username", $username);
@ -72,7 +71,6 @@ function attempt_login($conn, $username, $password) {
// Load results to variables // Load results to variables
$db_id = $result["user_id"]; $db_id = $result["user_id"];
$db_email = $result["email"];
$db_password = $result["password"]; $db_password = $result["password"];
$db_permissions = $result["permissions"]; $db_permissions = $result["permissions"];
@ -88,8 +86,7 @@ function attempt_login($conn, $username, $password) {
} }
// Set the session logged in user. // Set the session logged in user.
$_SESSION["current_user"] = new User($db_id, $username, $_SESSION["current_user"] = new User($db_id, $username, $db_permissions);
$db_email, $db_permissions);
} }
/** /**

View file

@ -46,7 +46,6 @@ display_header("About");
<ul> <ul>
<li> user_id </li> <li> user_id </li>
<li> user_name </li> <li> user_name </li>
<li> email </li>
<li> permissions </li> <li> permissions </li>
</ul> </ul>
You can learn more about what they mean in the You can learn more about what they mean in the
@ -68,10 +67,6 @@ display_header("About");
<b>username</b> <b>username</b>
This is the username the user chose at registration. This is the username the user chose at registration.
</li> </li>
<li>
<b>email</b>
This is the e-mail address the user provided at registration.
</li>
<li> <li>
<b>password</b> <b>password</b>
This is the string representation of your passw- I'm just kidding, This is the string representation of your passw- I'm just kidding,

227
docs/www/register.php Normal file
View file

@ -0,0 +1,227 @@
<?php
$COMMONS = $_SERVER['DOCUMENT_ROOT'] . "/../common";
include_once($COMMONS."/header.php");
display_header("Register");
// Define previous attempt and error variables and set to empty values.
$usernameOld = $passwordOld = $passwordConfOld = "";
$usernameErr = $passwordErr = "";
/**
* Process the information, and if there are no errors, log the user in.
*/
function attempt_register($conn, $username, $password, $passwordConf) {
// Access global variables
global $usernameOld;
global $passwordOld;
global $passwordConfOld;
global $usernameErr;
global $passwordErr;
// Check DB connection
if($conn == null){
printf("
<article>
<h1>Failed DB connection, cannot proceed!</h1>
If you see this error in production,
please shoot me an email with helpful details.
</article>");
include_once($GLOBALS['COMMONS']."/footer.php");
die();
}
// Sanitize inputs
$username = sanitize_input($username);
$password = sanitize_input($password);
$passwordConf = sanitize_input($passwordConf);
// Check if both mandatory fields are filled, if not, set appropriate error messages.
if (empty($username))
$usernameErr = "Please enter your username.";
if (empty($password))
$passwordErr = "Please enter your password.";
if($password != $passwordConf)
$passwordErr = "Password and confirmation are different.";
// If either of the fields were empty,
// set old values for prefill and return.
if(!empty($usernameErr) || !empty($passwordErr)) {
$usernameOld = $username;
$passwordOld = $password;
$passwordConfOld = $passwordConf;
return;
}
// See if a user with this name is already registered
$stmt = $conn->prepare("SELECT 1 FROM users WHERE username = :username;");
$stmt->bindParam(":username", $username);
// Execute the statement
$stmt->execute();
// Fetch the values
$result = $stmt->fetch(PDO::FETCH_ASSOC);
// If the user is already in the database, or is using a forbidden name
// set errors, old values, and return.
if($result || strtolower($username) == "[deleted]" ||
strtolower($username) == "[guest]" ||
strtolower($username) == "zeftax") {
$usernameErr = "This username is not available";
$usernameOld = $username;
$passwordOld = $password;
$passwordConfOld = $passwordConf;
return;
}
// Hash the password before inserting
$password = password_hash($password, PASSWORD_DEFAULT);
// Insert the user into database and print a success message.
$stmt = $conn->prepare("INSERT INTO users (username, password)
VALUES (:username, :password);");
$stmt->bindParam(":username", $username);
$stmt->bindParam(":password", $password);
// Execute the statement
$stmt->execute();
printf("<article><h2>Registration succesful!</h2>
You can now continue to
<a href=\"http://www.zdenekborovec-dev.cz/login\">Login</a>.
</article>");
}
/**
* If user sent the form, process it. This starts a session.
* Either login user and redirect to index or set error message variables.
*/
if (isset($_POST["submit"])) {
// Attempt to register
attempt_register($conn, $_POST["username"], $_POST["password"],
$_POST["password_conf"]);
}
?>
<article>
<form method="post" action="<?php
echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<h2> Register: </h2>
<table class="noborder-table"><tr>
<td> Username: </td>
<td>
<input type="text" name="username" tabindex="1"
autofocus="autofocus" value="<?php echo $usernameOld;?>">
</td>
<td>
<?php echo $usernameErr; ?>
</td>
</tr><tr>
<td> Password: </td>
<td>
<input type="password" name="password" tabindex="2"
value="<?php echo $passwordOld?>">
</td><td>
<?php echo $passwordErr; ?>
</td>
</tr><tr>
<td> Password confirmation: </td>
<td>
<input type="password" name="password_conf" tabindex="3"
value="<?php echo $passwordConfOld?>">
</td>
</tr></table>
<input name="submit" type="submit" tabindex="4" value="Send">
</form>
<hr>
<p>
Average time needed to crack a password with 12 RTX 4090 graphics cards
by length (<a href="https://www.hivesystems.com/password">source</a>,
<a href="https://images.squarespace-cdn.com/content/v1/
5ffe234606e5ec7bfc57a7a3/c8c21f1a-ac0a-4dd5-97bf-51a2e4fa63e4/
Hive+Systems+Password+Table+-+2024+Square.png">image</a>):
<table>
<tr>
<td><b>6</b></td>
<td> 12 hours </td>
<td></td>
<td><b>10</b></td>
<td> 33k years </td>
<td></td>
<td><b>14</b></td>
<td> 805bn years </td>
</tr>
<tr>
<td><b>7</b></td>
<td> 1 month </td>
<td></td>
<td><b>11</b></td>
<td> 2m years </td>
<td></td>
<td><b>15</b></td>
<td> 56tn years </td>
</tr>
<tr>
<td><b>8</b></td>
<td> 7 years </td>
<td></td>
<td><b>12</b></td>
<td> 164m years </td>
<td></td>
<td><b>16</b></td>
<td> 3qd years </td>
</tr>
<tr>
<td><b>9</b></td>
<td> 479 years </td>
<td></td>
<td><b>13</b></td>
<td> 11bn years </td>
<td></td>
<td><b>17</b></td>
<td> 276qd years </td>
</tr>
</table>
<p>
Note that these values assume that the attacker has access to a
database of hashed password, and is trying to log into as many
accounts as possible, so not really applicable for someone trying to
get into specifically your account and guessing the passwords,
but I believe it might still be a good wake-up call for people who
believe 6 or 8 characters are a "strong" password.
</p>
<p>
In case you do not read the linked article (which you should!...
if this interests you, that is. The site has a really shitty,
anti-user design, but the info is a good introduction to the topic)
also note that I took those values from the column assuming
combination of capitalised and non-capitalised letters,
numbers and special symbols.
</p>
</p>
<hr>
<p>
I recommend storing your login credentials safely on a piece of paper in a
locked book/drawer, or in an offline (or, if you need syncing, hosted
on-prem), encrypted FOSS password database (I recommend
<a href="https://keepassxc.org/">KeePassXC</a>). I would strongly advise
against reusing the same password and remembering it, or entrusting it
to some tech giant like mozilla, google, lastpass or whoever else
might be trying to convince you to store your passwords in their cloud.
</p>
<p>
Important thing to remember if you are trying to protect against a
<b>directed</b> attack is to keep the length of you password randomized
as well, If I were an attacker, and you revealed to me that you use 12
character password on my site, I am most likely going try that very
password an all the sites where I want to compromise you, and then
prioritize other 12 character passwords. By having your password length
random for each site (in a range you determine as safe, obviously),
you minimize this risk.
</p>
</article>
<?php
include_once($COMMONS."/footer.php");
?>