I have a site and I want to measure how long a client was connected to my site, one hour or two hour... or? how is it possible?
can someone help me in this regard.
it will be appreciated.
As mentioned in the comments, it's best to use analytic software but if you are looking for something simple (or just learning experience)
<?php
session_start();
if(!isset($_SESSION['sessionId'])) // No session, first time (subject to session timeout)
{
mysqli_query("INSERT INTO visitor_sessions(`started_on`, `last_checkin`) (" . time() . ", " . time() .")");
$_SESSION['sessionId'] = mysqli_insert_id(); // start the 'visiting session'
}
else
{
mysqli_query("UPDATE visitor set `last_checkin` = " . time() . " WHERE id = " .$_SESSION['sessionId']); // Update last checkin
}
?>
visitor_sessions is a table with 3 columns, id, started_on and last_checkin (timestamps).
You can include this script in your pages thus updating last check_in with each new page opened or have jquery call it every x seconds to maintain time even if they just view a page.
PS: Code was not tested but this is the general idea
Related
I am creating a lgoin time out. I have everything else working perfectly fine on my code. Here is my specification for the timeout:
If a user enters a password wrong 5 times within a 24hr period, lock them out for 48hrs.
If a user enters the password correctly, within the 5 attempts and 24hr period, reset their attempts.
I still need it to time the user out for 48 hours, and display a message letting the user know they have been timed out. If you could help me out with this I'd be really grateful. Here is the code snippet:
Here is a snippet of the code for the login attempt:
if (!$pw_ok) {
if (isset($_SERVER["REMOTE_ADDR"])) {
$str_RemoteHost = $_SERVER["REMOTE_ADDR"];
} else {
$str_RemoteHost = '';
}
$qry_WriteToDatabase = " INSERT INTO cms_user_login_attempts
(
cula_user_id,
cula_date_time,
cula_remote_host,
cula_attempt_count
)
VALUES (
" . $db->SQLString($row->user_id) . ",
Now(),
" . $db->SQLString($str_RemoteHost, true) . ",
'cula_attempt_count'
)";
$db->query($qry_WriteToDatabase);
$qry_UpdateCount = " UPDATE
cms_user_login_attempts
SET
cula_attempt_count = cula_attempt_count + 1
WHERE
cula_user_id = " . $db->SQLString($row->user_id) . " ";
$db->query($qry_UpdateCount);
$qry_CheckDatabase = " SELECT
CASE WHEN count(*) >= 5 THEN 0 ELSE 1 END as allowed_login
FROM
cms_user_login_attempts
WHERE
cula_date_time >= DATE_SUB(CURRENT_TIMESTAMP, interval 48 hour)
AND
cula_user_id = " . $db->SQLString($row->user_id) . "";
$rs_CheckDatabase = $db->query($qry_CheckDatabase);
if (! (isset($qry_CheckDatabase) && $qry_CheckDatabase)) {
$errors->defineError("invalid_user_pass", "Bleh.", array("username","password"));
}
}
edit: I have updated the question and code.
You need to save the login attempt before the password verification
if (! (isset($pw_ok) && $pw_ok))
Therefore, add a boolean field called cula_login_success to indicate if the password verification was successful.
And then query the number of failures in that date, the SQL should be something like this:
$qry="select cula_user_id,count(*) from cms_user_login_attempts where DATEDIFF(cula_date_time,NOW())<=2 and cula_user_id=".$db->SQLString($row->user_id)+" and not exist(select cula_user_id from cms_user_login_attempts where DATEDIFF(cula_date_time,NOW())<=2 and cula_user_id=".$db->SQLString($row->user_id)+" and cula_login_success=1) group by cula_user_id having count(*)>5";
This query should return an empty set, if it doesn't - then it means your user tries to login unsuccessfully more than 5 times, in 2 days, with no successful logins in between
table
--------------------------
user_id | attempts | datetime
Everytime login fails you add one to attempts and update datetime.
When the user logins correctly you update the db and set attempts to zero .
if attemts is equeal or greater than 5 you first check the datetime to see if its greater than 24 hours if so you login and reset attemts else you show a message and dont try to login.
In your table, you should be recording whether the attempt was successful or not. Then, before loading the form again, check if the user has 5 unsuccessful attempts within the last 24 hours and decide whether to lock the account or let the user try again.
DO NOT Do that....
If someone will quess user name, he can easly DDOS the person.
Its better to delay the login. Like - if wrong login count is hight (more than 5 for you) before checking the login use sleep for 10 seconds. This will sloow the atacks but still allow real user to log in.
If there is many failed logins (20-30) then block account for several minutes, and ban ip for hour or so.
That way your users would be able to login, and yet atackers would be blocked.
Basically, I've been trying to get an accurate measure of how many active users my site has. I'm tracking sessions on the DB, and also doing some clean-up based on the USER_AGENT to remove bots/spiders/crawlers (very basic stuff though).
What I get is a very high number of sessions, even after removing duplicate sessions for the same IP. In fact the number of sessions is 10x larger than what Google Analytics and other User Tracking systems report, so there's gotta be something I'm doing wrong.
Here's part of the code where I keep track of sessions:
//Start session if not active already
if(!isset($_SESSION)){
session_start();
}
//Determine whether bot or browser
$bots = array(
'bot',
'crawler',
'yahoo',
'spider',
'google',
'$^'
);
$ua = $_SERVER['HTTP_USER_AGENT'];
$uam = preg_match('/'.implode('|', $bots).'/i', $ua);
$uatype = ($uam)?'bot':'browser';
//Add session to DB if new or expired
if ($_SESSION['renew'] < time() || !isset($_SESSION['renew'])) {
$_SESSION['renew'] = time() + 900; //15 minutes
$sql = "INSERT INTO " . SESSIONS . " (session_id, user_id,
renew, user_ip, type, useragent) VALUES ('" . session_id() . "',
'" . $myuser->get('user_id') . "', " . $_SESSION['renew'] . ",
'" . $myuser->get('ip') . "', '$uatype', '$ua')
ON DUPLICATE KEY
UPDATE renew = " . $_SESSION['renew'] . ",
user_id = '" . $myuser->get('user_id') . "'";
$site_db->query($sql);
$sql = 'DELETE FROM ' . SESSIONS . '
WHERE renew < ' . time();
$site_db->query($sql);
}
So, I'm storing the session info in DB and then renewing / expiring every 15 minutes as necessary.
If I then query the DB for sessions that are from browsers, with unique IP addresses, I get about 10x as many as JS systems are reporting.
Even if I try to reduce the number by only counting entries that have their first two octets of the IP address unique, I'm still way over.
Any tips on what I could be doing wrong on my session tracking?
The query to get the counts goes like this:
$sql = "SELECT count(DISTINCT(user_ip) FROM ".SESSIONS." WHERE type = 'browser'";
As a note, the bot trap is already discarding about 66% of the sessions. If I didn't do that, I would get close to 40x as many "active users" as GA reports.
Thanks.
Maybe storing those records and then do a query like this:
$sql = 'SELECT COUNT(*) FROM ' . SESSIONS . ' WHERE renew BETWEEN ' . $expire-900. ' AND ' .$expire;
And for performance reasons, let a cronjob do your deleting.
For example: Delete every record that expired an hour ago. And do that every half hour or something.
I am currently using this php code to count the number of the users currently online:
$session_id = session_id();
$time_stamp = time();
$time_limit = $time_stamp - 300; // We give the session only 5 minutes if it exists
$result = $this->select("SELECT * FROM `online_visitors` WHERE `session_id`='$session_id' LIMIT 1");
if (!mysql_num_rows($result)) {
$tb_col[0] = "visitor_ip";
$tb_col[1] = "country";
$tb_col[2] = "session_id";
$tb_col[3] = "time_stamp";
$tb_col[4] = "last_time_stamp";
$tb_data[0] = "'" . $this->visitor_ip . "'";
$tb_data[1] = "'" . $this->visitor_country . "'";
$tb_data[2] = "'" . $session_id . "'";
$tb_data[3] = "'" . $time_stamp . "'";
$tb_data[4] = "'" . $time_stamp . "'";
$this->insert("`online_visitors`", $tb_col, $tb_data);
} else {
$this->update("`online_visitors`", "`visitor_ip`='$this->visitor_ip', `country`='$this->visitor_country', `last_time_stamp`='$time_stamp'", "`session_id`='$session_id'");
}
$this->delete("`online_visitors`", "`last_time_stamp`<'$time_limit'");
But it does not update in real time. I want to check the number of users every 30 seconds. I may also want to connect this table to the jQuery heartbeat function, so I know more reliably how many users are currently online.
Am I approaching this properly? Any tips for how to achieve this in jQuery (I'm not very good with it)? Or can my approach be improved?
I also want to improve my php code
You can also do this the other way around: instead of updating the time via ajax, you assume that the user is online until he leaves the page or closes the browser. In this case you use ajax to set the user as offline and execute it when browser fires onbeforeunload. In rare cases (power outage, system crash) this event will not be fired, so its a good idea to check also when the last update was made in case you have a floating user.
I get a list of records and each record is a question / answer / timestamp.
I created a basic PHP report:
<?php
$con = mysql_connect("localhost", "login", "pass");
if (!$con) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("db", $con);
$result = mysql_query(" SELECT *
FROM `experiment`
where userid = 73");
while ($row = mysql_fetch_array($result)) {
echo "question " . $row['question'] . "answer " . $row['answer'] .
"time " . $row['time'] . "stamp " . $row['createdAt'] . "<br>";
}
I need some way to compare the row in front of createdAt and the row after createdAt.
If the difference between two rows is bigger then 2 minutes, the thing should echo "warning".
I'll assume a couple of things on your behalf. This may change the value of the answer, but you simply haven't provided the necessary information for an answer to be feasible at this point.
I am going to assume that you are looping through the data records. You imply this by stating that there is a display of multiple rows. Your SQL query only gets the data of one row. I'll assume that you actually have gotten an entire record set instead. Because otherwise, the data structure needs to be examined for its design choices. I am also making an assumption on how userid is used in a table, mind, so that's my personal bias.
As record sets are collected, they can be manipulated. You're using the ancient mysql_* method here. I recommend that you read the PDO methodology that php has available at 5.2.7+ and consider upgrading your php version if you don't already have it.
The manipulation can take many forms.
$previousRecord = 0;
foreach ($recordSet as $index=>$record){
$recordSet[$index]['warningTime'] = FALSE;
if ($previousRecord){
if (($record['createdAt']-$previousRecord) > 120){
$recordSet[$index]['warningTime'] = TRUE;
}
}
$previousRecord = $record['createdAt'];
// Other data manipulation logic for page presentation
}
This should inject the warning right into the dataset that can be displayed whenever you want it to be. I do prefer a seperation of functions for maintainability; calling the database, extracting/formatting the data, displaying the data. It makes future changes much easier, also allows for code portability. You do not have this in your code, which means that whenever you do something like this again, well, you'll re-invent the wheel.
$createdAt = null;
while($row = mysql_fetch_array($result)) :
// initialise on first run
if ($createdAt === null) :
$createdAt = $row['createdAt'];
endif;
// now $createdAt is the value of the last row... if so, echo warning, else echo nothing
echo checkCreatedIsOlderThanTwoMinutes($createdAt, $row['createdAt']) === true ? "WARNING!" : "";
echo "question ". $row['question']. "answer ". $row['answer']. "time ".$row['time']."stamp ". $row['createdAt']."<br>";
endwhile;
I don't have a clue what the format of your createdAt looks like, so I use this pseudo-function:
function checkCreatedIsOlderThanTwoMinutes($oldCreatedAt, $newCreatedAd)
{
// check that stuff
}
Hope that helps.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to count the site current visitors using java script or php
I have an embedded stream on my website, but I want to pull the number of live viewers on the page. Is there a way to do this with PHP / AJAX, show the number of people currently viewing one of my webpages?
DISCLAIMER: I did something like this a LONG time ago, so here is the ugly old code (That I'm not going to put effort into making look nicer / not when I first started programming as this is just to give you an idea of how it can be done, and not to spoon feed any specific code).
$timeout = time() - (20);
$sessid_exist = mysql_query("SELECT sessid FROM bw_sessions WHERE sessid='" . session_id() . "'") or die (mysql_error());
$sessid_check = mysql_num_rows($sessid_exist);
if ($_SESSION['bw_username']) {
$sql = mysql_query("UPDATE bw_sessions SET timestamp='" . time() . "', username='" . $_SESSION['bw_username'] . "' WHERE sessid='" . session_id() . "'");
} else {
if($sessid_check > 0){
$sql = mysql_query("UPDATE bw_sessions SET timestamp='" . time() . "' WHERE sessid='" . session_id() . "'");
} else {
$sql = mysql_query("INSERT INTO bw_sessions (id, username, sessid, timestamp, ip)
VALUES(null, '', '" . session_id() . "', '" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "')") or die (mysql_error());
}
}
$sql = mysql_query("SELECT distinct sessid FROM bw_sessions WHERE username='' AND timestamp >= '$timeout' ORDER BY timestamp DESC") or die (mysql_error());
$sql2 = mysql_query("SELECT distinct sessid,username FROM bw_sessions WHERE username!='' AND timestamp >= '$timeout' ORDER BY username DESC") or die (mysql_error());
$num_guests = mysql_num_rows($sql);
$num_reg = mysql_num_rows($sql2);
?>
<font size='1'>Currently Online: <br>
<?=$num_guests;?> Guests<br>
<?=$num_reg;?> Registered users
You just need to make a table and hold session_id's.. then query that table for any "recent" activity. If you want real time updates, put code above (modified to your table design) in "online.php" and call it via jquery every x seconds, or however you decide to do it.
Something like Clicky should work for you.
If you've seen it somewhere, it probably IS possible, and this sort of thing is built into most forum sofware, and it's used on a lot of websites, so it's probably not that hard.
The usual way of doing this gets the IP of a connected visitor from $_SERVER['REMOTE_ADDR'] and then writes that to a file, and adding up all the unique IP's to find out how many people are connected.
This will need some sort of cleaning function to remove any IP's that are no longer connected.
The script runs on pageload, and counts visitors in a file, so if using ajax you run a PHP script polling that file every so often to update the count dynamically, or you could do it on pageload, but then ajax is'nt necessary as you could just do it with PHP.
If you don't already know how, figuring out how to run a PHP script in $.ajax is the first thing to do, then writing a function that counts visitors is probably the next.
I got 244 million hits on a search for such a script, and there's one here and here.