change status to 0 when user close browser - php

I'am trying to build a simple system to indicate weather the user is online or not. but I have one issue
when the user close the tap or the browser, the ajax code can't refresh the page that handles user track activity.
my php code that change the value to 0 if the user was inactive for 2 minutes
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 61)) {
$query = "UPDATE [ccc].[users] SET active = 0 WHERE ldap ='$ldap'";
sqlsrv_query($conn,$query);
}
jquery code to check every 5 seconds
$(document).ready(function () {
/*check existing users*/
function session_checking() {
$.post("../ajax-session.php", function (data) {
});
}
setInterval(session_checking, 5000);
});
How can I change the status to 0 if the user closed the browser ?

As far as I know, there is no way to notify the server when the user closes the tab/window.
Maybe you could create a task who constantly checks the activity of your users, inactivating them:
UPDATE users SET is_online = 0 WHERE is_online = 1 AND last_activity <= [WHAT YOU NEED]
Remember to create the proper indexes on your table, considering that you will run the above query frequently.

use setcookie for this
setcookie('newtest', 'newtest', 0);

Simply set a variable which has the session data at login process. So you may check whether user is active or not later. like:
$_SESSION["user"] = array(
"s_name" => "user1#email.com",
"login_time" => time()
);
if($_SESSION["user"]["login_time"] < time()+2*60){ unset($_SESSION["user"]); }
in application:
if(isset($_SESSION["user"])){ ... }

Related

Destroy PHP sessions by downtime

When you access the system, it generates a session as below:
session_start();
$_SESSION['Logged'] = time();
$_SESSION['Limit'] = 900; // 15 minutes
And when it exits the system, the session is destroyed.
The problem is when the user leaves the system without clicking the exit link and yes directly through the browser. How do I destroy the session by downtime? I tried the code below, but how do I know it's no longer in the system? It is necessary to change the status of the database and closing the system by the browser, I can not change.
session_start();
if($_SESSION['Logged'])
{
$seconds = time()- $_SESSION['Logged'];
}
if($seconds > $_SESSION['Limit'])
{
mysqli_query($this->conexao,"UPDATE table_admin SET StatusAdmin = 0 WHERE IdUser = '".$id."';");
session_destroy();
}
I'm sorry about my English.

PHP $_SESSION AND $_COOKIE Strange behavior

I'm trying to install COOKIES into my website.
I have found a script on GitHub: https://github.com/jotaroita/secure-login-php7-remember-register-resetpw
I have implemented the script and i'm able to login.
I'm able to login with just SESSION, or i can login with both SESSION and set a "Remember me -COOKIE".
To test the COOKIE i have set the SESSION to expire after 1 minute. $expireAfter = 1;
Senario:
I login to the website and check "remember me". Session starts and a cookie is set. Everything fine!
## last action: 1 seconds ago
skip the cookie check: session already set
I wait 60 seconds and reloads the page. Sessions destroys and Cookie reads:
## last action: 108 seconds ago
session destroy for inactivity
cookie read
cookie valid format
cookie right selector
cookie right token
set a new token in DB and in cookie
session set <- Within this message i can output Session data: $_SESSION['user'] at all times
BUT in my other page(home.php) $_SESSION['user'] is empty?! (I include the SESSION and COOKIE check from: check.php) if(isset($_SESSION['last_action'])){ returns true
If i wait another 60 seconds and reload the page if(isset($_SESSION['last_action'])){ returns false. But now the $_SESSION['user'] is set.
If i wait another 60 seconds and reload the page. if(isset($_SESSION['last_action'])){ returns true. But now the $_SESSION['user'] is empty.
home.php
<?php
//START SESSION
session_start();
//CONNECT TO DB, SET HEADER, SET TIMEZONE, CHECK FOR LOGIN-COOKIES
include("check.php");
//CHECK IF SESSION EXIST
if(!isset($_SESSION['user'])) {
$isSesstion = false;
header("Location: /index.php");
}
else{
$isSesstion = true;
}
.....
check.php
<?php
define ("PEPPER",''); //random string for extra salt, use if you want.
define ("WEBSITE",'mydomain.com'); //your web site without http:// without final /
define ("SCRIPTFOLDER",'/login'); //direcory of the script start with a / if you installed the script in the root write just a / never finish with a /
$hosting="localhost"; //your host or localhost
$database="db"; //your database name
$database_user="user"; //your username for database
$database_password="pwd"; //your database password
require_once('pdo_db.php');
//generate random sequence or numbers and letter avoid problems with special chars
function aZ ($n=12) {
$chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$bytes = random_ver($n);
$result="";
foreach (str_split($bytes) as $byte) $result .= $chars[ord($byte) % strlen($chars)];
return $result;
}
//generate random and avoid compatibility problem with php version
function random_ver ($n=10) {
$v=(int)phpversion()+0;
if ($v<7) {
//if php version < 7 use the old function for generate random bytes
return openssl_random_pseudo_bytes($n);
}else{
//random_bytes is better but works only with php version > 7
return random_bytes($n);
}
}
// ********************************
// * SESSION TIME UPDATE *
// ********************************
//Expire the session if user is inactive for 15 minutes or more.
//if u want to check how cookie works let the session id expire (wait X minutes without action, maybe set expireAfter to low value),
//close the browser then open again
$expireAfter = 1;
//Check to see if our "last action" session
//variable has been set.
if(isset($_SESSION['last_action'])){ echo 'IN';
//Figure out how many seconds have passed
//since the user was last active.
$secondsInactive = time() - $_SESSION['last_action'];
//Convert our minutes into seconds.
$expireAfterSeconds = $expireAfter * 60;
//Check to see if they have been inactive for too long.
$debug.="last action: $secondsInactive seconds ago<br>";
if($secondsInactive >= $expireAfterSeconds){
//User has been inactive for too long.
//Kill their session.
session_unset();
session_destroy();
$debug.="session destroy for inactivity<br>";
}
}
//Assign the current timestamp as the user's
//latest activity
$_SESSION['last_action'] = time();
// *********************************
// * CHECK AUTO LOG-IN WITH COOKIE *
// *********************************
//if session is not set, but cookie exists
if (empty($_SESSION['user']) && !empty($_COOKIE['remember']) && $_GET["logout"]!=1) {
$debug.="cookie read<br>";
list($selector, $authenticator) = explode(':', urldecode($_COOKIE['remember']));
//get from database the row with id and token related to selector code in the cookie
$sql = $db->prepare("SELECT * FROM user_tokens
WHERE selector = ? limit 1");
$sql->bindParam(1, $selector);
$sql->execute();
$row = $sql->fetch(PDO::FETCH_ASSOC);
if (empty($authenticator) or empty($selector))
$debug.="cookie invalid format<br>";
//continue to check the authenticator only if the selector in the cookie is present in the database
if (($sql->rowCount() > 0) && !empty($authenticator) && !empty($selector)) {
$debug.="cookie valid format<br>";
// the token provided is like the token in the database
// the functions password_verify and password_hash add secure salt and avoid timing attacks
if (password_verify(base64_decode($authenticator), $row['hashedvalidator'])){
//SET SESSION DATA
$sql = $db->prepare("SELECT * FROM users WHERE id = ?");
$sql->bindParam(1, $row['userid']);
$sql->execute();
$session_data = $sql->fetch(PDO::FETCH_ASSOC);
//UNSET VARS
unset($session_data['password']);
$_SESSION['user'] = $session_data;
//update database with a new token for the same selector and set the cookie again
$authenticator = bin2hex(random_ver(33));
$res=$db->prepare("UPDATE user_tokens SET hashedvalidator = ? , expires = FROM_UNIXTIME(".(time() + 864000*7).") , ip = ? WHERE selector = ?");
$res->execute(array(password_hash($authenticator, PASSWORD_DEFAULT, ['cost' => 12]),$_SERVER['REMOTE_ADDR'],$selector));
//set the cookie
$setc = setcookie(
'remember',
$selector.':'.base64_encode($authenticator),
time() + 864000*7, //the cookie will be valid for 7 days, or till log-out (if u want change it, modify the login.php file too)
'/',
WEBSITE,
false, // TLS-only set to true if u have a website on https://
false // http-only
);
$debug.="cookie right selector<br>cookie right token<br>set a new token in DB and in cookie<br>session set ".$_SESSION['user']['usr_fname']."<br>";
} else {
//selector exists but token doesnt match. that could be a secure problem, all selector/authenticator in database for that user will be deleted
$res=$db->prepare("DELETE FROM user_tokens WHERE userid = ".$row["userid"]);
$res->execute();
$debug.="cookie right selector<br>cookie wrong token (all DB entry for that user are deleted)<br>";
}
} else {
$debug.="selector not found in DB<br>";
}
} else {
$debug.="skip the cookie check: ";
if (!empty($_SESSION['user'])) $debug.="session already set<br>";
if (empty($_COOKIE['remember'])) $debug.="no cookie set<br>";
}
?>
So, whats wrong with the code?
Why is the $_SESSION filled with data every second time i refresh the webpage?
Why doesn't if(isset($_SESSION['last_action'])){ returns true everytime i refresh the page? And why does $_SESSION carry data in the debug message session set ".$_SESSION['user']['usr_fname']." all the time... but it is not carried over to home.php with the include(check.php"); ?
Do you need some more code? Just ask for it!
I think i found the problem.
After unset & destroy the session. I had to start a new session.
Strange thing this only happens every second time. But adding session_start(); solved the problem!
if(isset($_SESSION['last_action'])){
$secondsInactive = time() - $_SESSION['last_action'];
$expireAfterSeconds = $expireAfter * 60;
$debug.="last action: $secondsInactive seconds ago<br>";
if($secondsInactive >= $expireAfterSeconds){
//User has been inactive for too long.
//Kill their session.
session_unset();
session_destroy();
$debug.="session destroy for inactivity<br>";
}
}
...
session_start();
$_SESSION['user'] = $session_data;
...

Display Notifications

I'm trying to follow the first answer here in order to accomplish my alert feature on my app. Facebook like notifications tracking (DB Design)
but in that example, the user has to open the notifications page to check for new notifications. For me, i need to let user knows that there is a notification (database updated) by displaying an icon like Facebook alerts or something like that.
is there any clear idea about how to do that ?
EDIT
i did something but can't test it coz i don't have my laptop right now.
would you please take a look and let me know if something not OK ?
PHP file
$userID=$_GET["userid"];
//Database connection
$sql = 'SELECT count(*) as count FROM list_notifications WHERE userid ='.$userID;
$qry = pg_query($sql);
$row = pg_fetch_array($qry);
echo $row['count'];
jQuery & JavaScript
var old_count = -1;
setInterval(function() {
$.get("file.php", { userid: "userid" },
function(data){
if (data > old_count) {
alert("the list is updated with: " + data);
//OR
//console.log('the list is updated with:' + data);
old_count = data;
}
}
)},5000); // every 5 seconds
once the user is logged in, the userid must be sent periodically to the php file to check for new notifications. then display them to the user.
for count variable, i made it Increases incrementally with Database trigger.

Limt the amount a user downloads from a website, and redirect when limit is reached?

Sorry for the vague, title! I have a website with a lot of PDF files and limited monthly bandwith. What i would like to achieve (in PHP) is a way to limit each user ($_SESSION?) to a certain limit - say 50MB, and beyond that when they clicked to download another file they would be redirected to a webpage denying any further downloads (for the next 24 hours, say).
Is this possible? I'm not sure if my download "counter" can only count .pdf files (I dont want vistors to be blocked from browsing the site if they reach the limit). Any psuedo code would be greatly appreciated.
If you have all of your downloads go through a single php script:
<a href="download.php?file='filename.pdf'" />
You can do pretty much whatever you want. That php file can deliver all of your files (keeping them out of the webroot), write to your _SESSION, and it can perform your redirect. Enjoy.
If you already have a user system, I would recommend to store all information within the users profile.
So there's no problem if he deletes all his cookies and relogins!
And for guests, I would recommend captchas and session or IP based restrictions.
// Pseudo code
// download.php
function UserHasReachedLimit($file)
{
$info = $Database->QueryUserInfo('limit');
$max = $Database->GetLimitForFile($file);
if ( $info[$file] > $max )
return false;
else
return true;
}
if ( IsUser() )
{
if ( UserHasReachedLimit() )
error();
else
download();
}
else // guest
{
// session or IP based restrictions...
}
I'd probably stay away from sessions for this. Sessions are volatile and susceptible to various browser behavior. For example, in Firefox if a session is initialized, I can close Firefox, visit the same site, and session is still active. However in IE if I open up multiple tabs and visit the same site, each tabbed instance gets a new session id.
I'd recommend setting up an account system where a user has to log into your site. Then you can track their download amount at the account level, which will persist between multiple sessions.
I think you are trying to avoid forcing user to register in your site, while you are trying to track per visitor bandwidth with is unpractical with the common ways(cookies, ip ...). So, the best way(in my opinion, of course there are many improved solutions) is to make a simple registration form, say name, password and email, put an activation system per email to protect your site from of user, now each user logged in and tried to download a file, you process his request in the following steps:
1) user request for file name.pdf (check its availability and size(important)).
2) check user bandwidth:
$query = sql_query("SELECT Bandwidth, LastDownload FROM Users, Stats WHERE USER_ID=5");
$result = sql_fetch($query);
if ($result['Bandwidth'] < 50M)
showDownloadLink();
else if($result['LastDownload'] - currentTime() !=0)
echo "please wait to the next 24h";
Database should be like this:
Users:
ID_U int(key, auto increment), Name varchar(25), email varchar(255), password varchar(32), Bandwith float
Stats:
ID_S int(key, auto increment), LastDownload time, ID_U integer
Note:
Each time user download a file, you update Bandwidth row for the right user, so later you can check if particular user reach its limit or not. You have also to reset it after each 24H.
This is a generic solution and many thinks have to be checked, like the counter bandwidth must be reset every 24H.
Create a table to store count downloads
CREATE TABLE IF NOT EXISTS `downloaded` (
`ip` varchar(200) NOT NULL,
`count` int(11) NOT NULL DEFAULT '0',
`last_access` datetime DEFAULT NULL,
UNIQUE KEY `ip` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
<?php
/*
$limit => Number of Downloads Allowed
$period => In minutes
*/
function UserHasReachedLimit($limit, $period) {
$ip = addslashes($_SERVER['REMOTE_ADDR']);
$dl = false;
$sql = sprintf("SELECT UNIX_TIMESTAMP(last_access) last_time, count FROM downloaded WHERE ip = '%s' ORDER BY last_access DESC", $ip);
$res = mysql_query($sql);
if (mysql_num_rows($res) > 0) { // There is a registered IP already
$last_xs = mysql_result($res, 0, 'last_time');
$last_xs += $last_xs+$period * 60;
$count = mysql_result($res, 0, 'count'); // number of downloads by this ip
if ($count == $limit && $last_xs > time()) { // we check if downloads reached in this period
$dl = true;
} else {
$sql = sprintf("UPDATE downloaded SET count = CASE WHEN count >= %s THEN 0 ELSE count+1 END, last_access=now() WHERE ip ='%s'", $limit+1, $ip); // we just update download count + 1
mysql_query($sql);
}
} else { // There is not a registered IP and we create it
$sql = sprintf("INSERT INTO downloaded VALUES ('%s', '0', NOW());", $ip); mysql_query($sql);
}
return $dl;
}
/*
Usage
*/
$limit = 2;
$period = 2;
if(UserHasReachedLimit($limit, $period) == true) {
// User reached number of 2 downloads in 2 minutes
} else {
// Continue downloading
}
?>

Trying to get a login to last 10 days

I'm using a login system, and I'm trying to keep the user logged in for 10 days unless they specifically log out. I thought by using session_set_cookie_params('864000'); that it would make the user stay logged in for 10 days. But it's not doing that, at least in Chrome. The user only seems to be logged in for the standard 20-30 minutes before being automatically logged out. When I check the cookies in Chrome, there are two PHP Session cookies listed for my URL with expiration dates 10 days into the future. But this seems to be unrelated to the login variables. Most of the relevant code should be below.
Any idea why the user is not logged in for 10 days?
Thanks in advance,
John
In the index file, I have the following:
require_once "header.php";
//content
include "login.php";
In the header.php file, the following is included:
session_set_cookie_params('864000');
session_start();
In the login.php file, the following is included:
if (checkLogin($_POST['username'], $_POST['password']))
{
show_userbox();
}
Here is the function "checkLogin":
function checkLogin($u, $p)
{
global $seed; // global because $seed is declared in the header.php file
if (!valid_username($u) || !valid_password($p) || !user_exists($u))
{
return false; // the name was not valid, or the password, or the username did not exist
}
//Now let us look for the user in the database.
$query = sprintf("
SELECT loginid
FROM login
WHERE
username = '%s' AND password = '%s'
AND disabled = 0 AND activated = 1
LIMIT 1;", mysql_real_escape_string($u), mysql_real_escape_string(sha1($p . $seed)));
$result = mysql_query($query);
// If the database returns a 0 as result we know the login information is incorrect.
// If the database returns a 1 as result we know the login was correct and we proceed.
// If the database returns a result > 1 there are multple users
// with the same username and password, so the login will fail.
if (mysql_num_rows($result) != 1)
{
return false;
} else
{
// Login was successfull
$row = mysql_fetch_array($result);
// Save the user ID for use later
$_SESSION['loginid'] = $row['loginid'];
// Save the username for use later
$_SESSION['username'] = $u;
// Now we show the userbox
return true;
}
return false;
}
Looks more likely that your server is discarding the sessions -- you'd need to store pertinent information in a local friendly database and load from there, based on the cookies as appropriate

Categories