I want to block a someone who tried to login 4 times with a wrong password.
The problem is: When I use "modify" and change the timestamp with 15 minutes, I get -1 as output and after two minutes I get -2 as output. I tied for so long and I searched a lot on internet, but it still doesn't work.
How I want it to work:
In the database is the column: "falselog". If the username of the visiter is correct but the password is incorrect, falselog will be +1. When falselog is 4, the visiter will be banned for 15 minutes. So the visiter is able to try 4 times. After 15 minutes, the visiter can try again.
This is my object with all the code:
public function logUser($username, $password) {
// query id = 2
$sql2_1 = "SELECT
id,
password,
falselog,
lastlogin
FROM users
WHERE username ='".$username."' ";
$result2_1 = $this->con->query($sql2_1);
$fetch2_1 = mysqli_fetch_array($result2_1);
$count2_1 = $result2_1->num_rows;
$now = new DateTime('now');
$blockedSince = new DateTime($fetch2_1['lastlogin']);
$fout = $fetch2_1['falselog'];
$date_old = date ("Y-m-d H:i:s", strtotime("now"));
$block = date("i", $fetch2_1['lastlogin']) + 16;
$current = date("i", strtotime("now"));
$wait = $block - $current ;
$dbtime = date ("Y-m-d H:i:s", strtotime($date_old));
// This is the code that doesn't work
if ($fetch2_1['falselog']>=4 AND $blockedSince->modify('+15 minutes') > $now) {
$error[] = 'This account has been banned, try again about '.$wait.' minutes';
$decline = true;
$date_old = $fetch2_1['lastlogin'];
}
elseif (!preg_match("/^[A-Za-z0-9-]+$/", $username)) {
$error[] = 'De input bevat ongeldige tekens (alleen cijfers en letters toegestaan)';
}
elseif ($count2_1 === 0) {
$error[] = 'Wrong login data';
}
elseif ($fetch2_1['password']!=sha1($password)) {
$error[] = 'wrong password';
$fout = $fetch2_1['falselog']+1;
}
if ((count($error) == 0) OR ($fetch2_1['falselog']==4 AND $blockedSince->modify('+15 minutes') < $now)) {
$fout = 0;
}
$sql2_2 = "UPDATE users SET
falselog='".$fout."',
lastlogin='".$dbtime."'
WHERE username='".$username."' ";
if ($this->con->query($sql2_2) === TRUE) {
if (count($error) == 0) {
return false;
}
else {
return $error;
}
}
else {
echo "Error: " . $sql2_2 . "<br>" . $this->con->error;
return true;
}
}
You should check that here
$blockedSince = new DateTime($fetch2_1['lastlogin']);
you get the correct data for DateTime, try var_dump($blockedSince); after this line, and check that it has correct value inside;
try this
$blockedSince = mktime($fetch2_1['lastlogin']);
Related
my first time writing prepared statement
this code is checking your late in every 3 hours then inserting the time interval into db
date_default_timezone_set('Asia/Hong_Kong');
$now = new DateTime();
if ($now->format("H:i") > "22:00") {
$deadline = DateTime::createFromFormat("H:i", "22:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "19:00") {
$deadline = DateTime::createFromFormat("H:i", "19:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "16:00") {
$deadline = DateTime::createFromFormat("H:i", "16:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "13:00") {
$deadline = DateTime::createFromFormat("H:i", "13:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "10:00") {
$deadline = DateTime::createFromFormat("H:i", "10:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "07:00") {
$deadline = DateTime::createFromFormat("H:i", "07:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
}
$stmt = $conn->prepare("INSERT INTO time_in (e_id, login, late, date_in)
VALUES (?, ?, ?,CURRENT_TIMESTAMP)");
$stmt->bind_param("sss", $e_id, $login, $diff->format('%H:%i'));
$e_id = "id is unavailable"; // changing to $_POST in the future
$login = "1";
$status = $stmt->execute();
if(!$status) {
echo $stmt->error;
exit;
}
echo "success";
}
and im getting this
Notice: Only variables should be passed by reference
at this line $stmt->bind_param("sss", $e_id, $login, $diff->format('%H:%i'))
the code working perfectly but im getting that notice
please help
you must pass actual variables to bind_param, since $diff->format('%H:%i') is not a variable but rather the output of a function, it doesn't like that.
You will need to assign this to a variable first then pass it in. i.e
$diffFormat = $diff->format('%H:%i');
$stmt->bind_param("sss", $e_id, $login, $diffFormat);
I have hundreds of response from php IMAP (fetching email), I wanted to insert all the fetched email into database. Problem is that on server stay time is 40 second (Host provider said to me) and my script is taking more than 40 second. Due to the fetching records and insert queries server returning the following error.
[an error occurred while processing this directive]
Here is Php Code
$imap = #imap_open("{mail.******.com:143/novalidate-cert}", '*****#***.com', '*****');
if(isset($imap)){
$message_count = #imap_num_msg($imap);
$array_mail = array();
if($message_count > 0){
for ($m = 1; $m <= $message_count; ++$m){
//$header = #imap_header($imap, $m);
$header = #imap_rfc822_parse_headers(imap_fetchheader($imap, $m));
$email[$m]['from'] = $header->from[0]->mailbox.'#'.$header->from[0]->host;
$from = $email[$m]['fromaddress'];
$from_email = $email[$m]['from'];
$array_mail[] = $from_email;
if(isset($header->cc)){
$hedCC = $header->cc;
foreach($hedCC as $s){
//echo $s->mailbox.'#'.$s->host.'<br />';
$array_mail[] = $s->mailbox.'#'.$s->host;
}
}
if(isset($header->to)){
$hedTO = $header->to;
foreach($hedTO as $t){
//echo $t->mailbox.'#'.$t->host.'<br />';
$array_mail[] = $t->mailbox.'#'.$t->host;
}
}
}
$i = 0;
if (!empty($array_mail)) {
$insertCount = 0;
foreach($array_mail as $m_){
// INSERT HERE
//echo $m_.'<br />';
$isExistWithID = $this->isExistWithID($user_id,$m_);
$email_err = $this->isValidEmail($m_);
$isValid = 0;
if($email_err == false){
$isValid = 1;
}
if($isExistWithID==0 && $isValid==0){
$insert = $this->pdoConnection->prepare("
INSERT INTO ws_email (
u_id,
we_email,
date_added
)
VALUES(
:u_id,
:we_email,
:date_added
)
");
$insert->bindParam(':u_id', $u_id);
$insert->bindParam(':we_email', $we_email);
$insert->bindParam(':date_added', $date_added);
// Insert Data
$u_id = $_SESSION['USERID'];
$we_email = $m_;
$date_added = date("Y-m-d H:i:s");
if($insert->execute()){
$insertCount++;
}
}
$i++;
}// end foreach
$response['success'] = $insertCount.'Email address(s) fetched successfully.';
}
//echo $i;
//
}else{
$response['error'] = 'No record found';
}
}else{
$response['error'] = 'IMAP does not connect';
}
}//end if error is equal to 0
/************ END NEW 29 SEP *************/
echo json_encode($response, JSON_PRETTY_PRINT);
I tried to optimize the code as i can, but still taking long time and due to this server returning the error.
I would like to request to you kindly guide me how can i optimize it. Thank You.
I have been working towards updating a password after a request has been sent and collected from email, the request part seems to work but when I try to update the password nothing seems to happen, my password length is set at 255, initially I checked if it was the correct id I was getting and it seems to be, when I manually run the query in easyphp adding what I want updated it seems to work, I have looked at my network response no errors are showing and checked my error logs nothing there either. Any advice would be great.
<?php
require_once'connection.php';
$userInput = new UserInput();
$userInput->trimInput();
$id = '';
if( isset( $_GET['reset'])) {
$id = $_GET['reset'];
}
header('Content-Type: application/json');
$errors = [];
if (empty($_SESSION['resetPassword'])) {
$_SESSION['resetPassword'] = 1;
}
else {
$_SESSION['resetPassword']++;
}
if($_SESSION['resetPassword'] > 3){
$errors[]= ["name"=>"username","error"=>"Too many attempts try again in 15 minutes"];
if(!isset($_SESSION["timeoutPassword"])){
$_SESSION['timeoutPassword'] = time();
};
$st = $_SESSION['timeoutPassword'] + 900;
if(time() > $st){
unset($_SESSION['resetPassword']);
unset($_SESSION['timeoutPassword']);
}
}
else {
if(filter_var($_GET['password'], FILTER_VALIDATE_REGEXP,["options"=> [ "regexp" => "/.{6,25}/"]]) === FALSE){
$errors[]= ["name"=>"password","error"=>"invalid password (6 to 25 characters)"];
}
if(!preg_match("/(?=[a-z]*[0-9])(?=[0-9]*[a-z])([a-z0-9-]+)/i",$_GET['password'])) {
$errors[]= ["name"=>"password","error"=>"Password must contain numbers and letters"];
}
if($_GET['password'] !== $_GET['repeatPassword']){
$errors[]= ["name"=>"repeatPassword","error"=>"passwords don't match"];
}
if (count($errors) === 0) {
try{
$sql = "UPDATE username SET activecode = 'Active', password = :password WHERE activecode = :reset";
$stmt = $db->prepare($sql);
$stmt->bindValue(':password', password_hash($_GET['password'], PASSWORD_DEFAULT));
$stmt->bindValue(':reset', $id);
$stmt->execute();
$stmt->rowCount();
if ( $stmt->rowCount() === 1){
echo json_encode(["success"=>"Your password has been reset"]);
exit(0);
}
}
catch(Exception $e ) {
$errors[]= ["name"=>"username","error"=>"Unable to update password"];
}
}
}
echo json_encode(["errors"=>$errors]);
I am using a simple script at the top of every page that will update a LastActive column in the database:
$username = $_SESSION['username'];
$userID = $_SESSION['user_id'];
if(isset($username, $userID)) {
if ($insert_stmt = $mysqli->prepare("UPDATE Users SET lastActive = DATE_ADD(Now(), interval 6 hour) WHERE username = ?")) {
$insert_stmt->bind_param('s', $username);
// Execute the prepared query.
if (! $insert_stmt->execute()) {
$insert_stmt->close();
header('Location: ../headers/error.php?err=Failed Upload');
}
}
$insert_stmt->close();
}
I always want to keep performance and security in mind. Would this lead to poor performance in the future with 000's of connections?
How does using cookies (not that I know how) differ from a simple script like this?
Thanks
edit:
$username = $_SESSION['username'];
$userID = $_SESSION['user_id'];
$loginTime = $_SESSION['timestamp'];
date_default_timezone_set("Europe/London");
$now = new DateTime();
$diff=$now->diff($loginTime);
$minutes = $diff->format(%i);
if(isset($username, $userID) && $minutes> 30) {
$_SESSION['timestamp'] = $now;
$online = true;
}
Couple of suggestions:
You could do this via AJAX, so that the LastVisited is updated asynchronously after the user's page loads. That way, there won't be any impact to the page load time for the user.
If, for any reason, your SQL query fails, you should fail silently. Since recording Last Visited is not business critical, you should not redirect the user to an error page. Maybe just log an error, and set up an alert so if there are multiple failures, you get alerted and can take a look at it.
All that you made with cookies will be data supplied by your users, then you cannot trust it.
In other hand, if you work with cookies, all of them will travel in each request header.
You should do it in server side and yes, a database is not performant.
You can try to persist this information with something like Redis, a in-memory data structure store, used as database, cache and message broker.
I thought I'd post the way I got around this for any one else looking for a User Online type method. Of course this might have been done much better but works in my situation.
I am using both database entries and session to test if a user is online.
On user login I update a column in my users table with a Now() timestamp and add this to their session data.
At the top of each page I am running a script to check if the user is logged in and get their timestamp from session data. if this data is 45 minutes old, the script will update the table setting the lastActive column of my users table to Now();
<?php
include_once 'functions.php';
if(isset($_SESSION['username'], $_SESSION['user_id'], $_SESSION['lastActive'])) {
date_default_timezone_set("Europe/London");
$now = new DateTime();
$lastActive = $_SESSION['lastActive'];
$diff=$now->diff($lastActive);
$hours = $diff->format('%h');
$mins = $diff->format('%i');
$day = $diff->format('%d');
$month = $diff->format('%m');
$year = $diff->format('%y');
if($mins > 45 || $hours >= 1 || $day >= 1 || $month >= 1 || $year >= 1) {
$_SESSION['lastActive'] = $now;
set_last_active($mysqli, $_SESSION['username']);
}
}
set_latst_action is simply just:
function set_last_active($mysqli, $username) {
if ($stmt = $mysqli->prepare("UPDATE Users SET lastActive = Now() WHERE username = ?")) {
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->close();
}
}
then when I want to see if a user is online for example on a profile page I call isOnline();
function isOnline($mysqli, $username) {
if ($stmt = $mysqli->prepare("SELECT lastActive FROM Users WHERE username = ? LIMIT 1")) {
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows == 1) {
$stmt->bind_result($return);
$stmt->fetch();
$lastActive = $return;
} else {
// user does not exist
$lastActive = "";
return $lastActive;
$stmt->close();
}
} else {
// SELECT failed
$lastActive = "";
return $lastActive;
$stmt->close();
}
if (!empty($lastActive)) {
date_default_timezone_set("Europe/London");
$dateNow = new DateTime;
$lastActiveDate = new DateTime($lastActive);
$diff=$dateNow->diff($lastActiveDate);
$hours = $diff->format('%h');
$mins = $diff->format('%i');
$day = $diff->format('%d');
$month = $diff->format('%m');
$year = $diff->format('%y');
if ($mins > 45 || $hours >= 1 || $days >= 1 || $month >= 1 || $year >= 1) {
$return = "Offline";
return $return;
}
else {
$return = "Online";
return $return;
}
}
else {
$return = "Offline";
return $return;
}
}
I am using the following code to determine if a user is signed in or not, I have set the field 'first_sign_in' to 0 in the mysql table but I am still receiving the echo 'already signed in for the start of the day when actually it should return 'not signed in for the start of the day'
Could someone help me on where I am going wrong here.
$time = date('h:i:s', time());
$checkifstaffexists = mysql_query("SELECT user_id from staff WHERE pin = 3012");
if (!$checkifstaffexists) {
die('Failed.');
}
if (mysql_num_rows($checkifstaffexists) > 0) {
$checkfirstsignin = mysql_query("SELECT first_sign_in from staff WHERE pin = 3012");
if ($checkfirstsignin == 0) {
echo 'not signed in for start of day</br>';
$checksignintime = mysql_query("SELECT " . date("d") . " " . "_start from staff WHERE pin = 3012");
if($checksignintime > $time) {
echo 'user is late';
$addtolatetable = mysql_query("INSERT INTO lates (user_id, date_time) SELECT user_id, '2014-05-15 12:00:00' from staff WHERE pin = 3012");
//$signuserin = mysql_query(" ");
$changestatustoin = mysql_query("UPDATE staff SET status=1 WHERE pin = 3012");
//redirect
} else {
echo 'user is not late';
//$signuserin = mysql_query(" ")
$changestatustoin = mysql_query("UPDATE staff SET status=1 WHERE pin = 3012");
//redirect
}
} else {
echo 'already signed in for start of day</br>';
$checkifuserisinourout = mysql_query("SELECT status from staff WHERE pin = 3012");
if ($checkifuserisinourout == 0) {
echo 'user is not signed in so we will sign you in';
//$signuserin = mysql_query(" ");
$changestatustoin = mysql_query("UPDATE staff SET status=1 WHERE pin = 3012");
//redirect
} else {
echo 'user is signed in so we will sign you out';
//$signuserout = mysql_query(" ");
$changestatustoout = mysql_query("UPDATE `staff` SET status=0 WHERE pin = '3012'");
//redirect
}
}
} else {
//The user cannot be found
echo 'User doesn\'t exist.';
}
with the line
$checkfirstsignin = mysql_query("SELECT first_sign_in from staff WHERE pin = 3012");
you get back a resource that you have to use to fetch data, for example:
$row = mysql_fetch_assoc($checkfirstsignin);
and with this array ($row) you can work further.
Please check the manpage for mysql_query for further reading...
and since this will be posted all the time: mysql_* methods are deprecated, please use mysqli or pdo.
if ($checkfirstsignin == 0)
Will always equal true if the query succeeds even if there are no matching results.
You need to use mysql_fetch_row or mysql_fetch_array to do that.
while($row = mysql_fetch_assoc($checkfirstsignin)){
if($row['first_sign_in']==0){
//do something
}
}
Write this var_dump( $checkfirstsignin );
after this line $checkfirstsignin = mysql_query("SELECT first_sign_in from staff WHERE pin = 3012");
And you will see the returned result is an array, so it is always false on the next if check.