Currently I'm tracking time spent by user on website using PHP code mentioned below:
if (!isset($_SESSION[timeset1]))
{
$one_val = time();
$_SESSION[timeset_dummy]= $one_val;
$two_val = time()+1;
$_SESSION[units_all] = array
(
"year" => 29030400,
"month" => 2419200,
"week" => 604800,
"day" => 86400,
"hr" => 3600,
"min" => 60,
"sec" => 1
);
}
else
{
$two_val = time();
}
$diff = abs($two_val - $_SESSION[timeset_dummy]);
foreach($_SESSION[units_all] as $unit => $mult)
if($diff >= $mult)
{
$output .= " ".intval($diff / $mult)." ".$unit.((intval($diff / $mult) == 1) ? ("") : ("s"));
$diff -= intval($diff / $mult) * $mult;
}
I want to give pop-up to users after 8 mins of inactivity that session will expire in next 2 mins. Can you please suggest how can I show pop-up (preferably without using Javascript, nice to have with CSS3 & HTML5) . Pop-Up will have warning message "Do you want to continue" and one button "Yes" , if button is not clicked for 2 mins automatically page logout script (PHP) will be executed.
Any pointers to to get this logic implemented.
I found a jQuery plugin that looks like it will make your life easier. It is called jquery-idleTimeout.
The plugin has a few configuration items so you can customize it for your own needs…
inactivity: 1200000 //20 Minute default (how long before showing the notice)
sessionAlive: 300000, //5 minutes default how often to hit alive_url, we use for our ajax * interfaces where the page doesn’t change very often. This helps to prevent the logout screen of your app appearing in ajax callbacks. If you set this to false it won’t send off.
alive_url: ‘/path/to/your/imHere/url’, //send alive ping to this url
redirect_url: ‘/js_sandbox/’, //Where to go when log out
click_reset: true, //Reset timeout on clicks (for ajax interface) – resets the sessionAlive timer, so we are not hitting up your app with alive_url if we just did an ajax call for another reason.
logout_url: ‘/js_sandbox/timedLogout/index.html’ //logout before redirect (url so you can completely destroy the session before redirecting to login screen)
Here is a link to the github page to download the library.
https://github.com/philpalmieri/jquery-idleTimeout
Edit
Something I also noticed while looking at the source code, they are using jquery-ui as their stylesheet to make it look like it does in the demo.
As far as I know, you cannot achieve what you are looking for without javascript. The browser needs javascript to know when to open the pop-up. You can use whatever means you want to check for timeout, either the basic window.setTimeout or a more advanced library (like the one in tehAon's answer).
Since I cannot post a comment I'm going to ask here: your code seems awfully complicated for checking if a user is still active. Is there any particular reason you could not use something like this:
$_SESSION['last_activity'] = time();
function check_if_logged_in() {
if(time() - $_SESSION['last_activity'] > 600) { // 10 minutes but you could use 480 for 8 minutes
// Do redirect or take other action here
}
}
if(time() - $_SESSION['timestamp'] > 900) { //15 minute subtract new timestamp from the old one
$_SESSION['logged_in'] = false;
session_destroy();
header("Location: " . index.php); //redirect to index.php
exit;
} else {
$_SESSION['timestamp'] = time(); //set new timestamp
}
This is quite easy with php session variable.
set $_SESSION variable with timestamp and check with the action time
<?php
session_start();
if(time()-$_SESSION['time']>600)
unset($_SESSION['time']);
else
$_SESSION['time']=time();//updating with latest timestamp
?>
Related
I am creating a session when a user logs in like so:
$_SESSION['id'] = $id;
How can I specify a timeout on that session of X minutes and then have it perform a function or a page redirect once it has reached X minutes??
EDIT: I forgot to mention that I need the session to timeout due to inactivity.
first, store the last time the user made a request
<?php
$_SESSION['timeout'] = time();
?>
in subsequent request, check how long ago they made their previous request (10 minutes in this example)
<?php
if ($_SESSION['timeout'] + 10 * 60 < time()) {
// session timed out
} else {
// session ok
}
?>
When the session expires the data is no longer present, so something like
if (!isset($_SESSION['id'])) {
header("Location: destination.php");
exit;
}
will redirect whenever the session is no longer active.
You can set how long the session cookie is alive using session.cookie_lifetime
ini_set("session.cookie_lifetime","3600"); //an hour
EDIT: If you are timing sessions out due to security concern (instead of convenience,) use the accepted answer, as the comments below show, this is controlled by the client and thus not secure. I never thought of this as a security measure.
Just check first the session is not already created and if not create one. Here i am setting it for 1 minute only.
<?php
if(!isset($_SESSION["timeout"])){
$_SESSION['timeout'] = time();
};
$st = $_SESSION['timeout'] + 60; //session time is 1 minute
?>
<?php
if(time() < $st){
echo 'Session will last 1 minute';
}
?>
<script type="text/javascript">
window.setTimeout("location=('timeout_session.htm');",900000);
</script>
In the header of every page has been working for me during site tests(the site is not yet in production). The HTML page it falls to ends the session and just informs the user of the need to log in again. This seems an easier way than playing with PHP logic.
I'd love some comments on the idea. Any traps I havent seen in it ?
<?php
session_start();
if (time()<$_SESSION['time']+10){
$_SESSION['time'] = time();
echo "welcome old user";
}
else{
session_destroy();
session_start();
$_SESSION['time'] = time();
echo "welcome new user";
}
?>
Byterbit solution is problematic because:
having the client control expiration of a server side cookie is a security issue.
if expiration timeout set on server side is smaller than the timeout set on client side, the page would not reflect the actual state of the cookie.
even if for the sake of comfort in development stage, this is a problem because it won't reflect the right behaviour (in timing) on release stage.
for cookies, setting expiration via session.cookie_lifetime is the right solution design-wise and security-wise! for expiring the session, you can use session.gc_maxlifetime.
expiring the cookies by calling session_destroy might yield unpredictable results because they might have already been expired.
making the change in php.ini is also a valid solution but it makes the expiration global for the entire domain which might not be what you really want - some pages might choose to keep some cookies more than others.
session_cache_expire( 20 );
session_start(); // NEVER FORGET TO START THE SESSION!!!
$inactive = 1200; //20 minutes *60
if(isset($_SESSION['start']) ) {
$session_life = time() - $_SESSION['start'];
if($session_life > $inactive){
header("Location: user_logout.php");
}
}
$_SESSION['start'] = time();
if($_SESSION['valid_user'] != true){
header('Location: ../....php');
}else{
source: http://www.daniweb.com/web-development/php/threads/124500
<?php
session_start();
if($_SESSION['login'] != 'ok')
header('location: /dashboard.php?login=0');
if(isset($_SESSION['last-activity']) && time() - $_SESSION['last-activity'] > 600) {
// session inactive more than 10 min
header('location: /logout.php?timeout=1');
}
$_SESSION['last-activity'] = time(); // update last activity time stamp
if(time() - $_SESSION['created'] > 600) {
// session started more than 10 min ago
session_regenerate_id(true); // change session id and invalidate old session
$_SESSION['created'] = time(); // update creation time
}
?>
In this code I'm trying to ban client if he/she/it doing to much(10) login request for 3 minutes. The problem is after 3 minutes user must refresh the page 2 times. I can see the reason why it's enter into if statement but I can't find the solution. I feel like I've overcoded.
if($this->sessions->get_data("wrong_login")>10){
if(!isset($_SESSION["ban_time"])){
$this->sessions->set_data("ban_time", time());
}else
{
if(time() - $this->sessions->get_data("ban_time") > 180){ // 180 seconds
$this->sessions->remove("ban_time");
$this->sessions->remove("wrong_login");
}
}
// The message if user still banned
die("Banned for 3 minutes!");
}
I hope I can tell the problem..
EDIT: This code is the inside of the construct of register controller.
Before your IF statement, add another if statement that checks for ban_time session if the time is up, then set the wrong_login session to 0 if it is.
if($this->sessions->get_data("ban_time") < time())
{
$this->sessions->remove("ban_time");
$this->sessions->set_data("wrong_login", 0);
}
remove your else statement there.
also forgot to mention! when you set the ban time, it should be time() + 180.
if(!isset($_SESSION["ban_time"])){
$this->sessions->set_data("ban_time", time()+180);
}
use header function.
e.g.
header("Location: /path/to/some/file.php?error=Banned for 3 minutes.");
Then on the file.php you can do this:
<?php
// Parse error
$error = isset($_GET['error']) ? $_GET['error'] : '';
// Display error (if any) and stop executing the rest of the code.
if (!empty($error)) {
exit($error);
}
?>
This will not work if you already started to output...
I am trying to create a hit counter for my website and I have developed the following code for it. I have included the following code only in Codeigniter's main controller for my home page.
At first I thought the code was working fine but I just found that if I don't keep on browsing the pages then again go to the home page it doesn't update the data. I mean for example: If I go to my homepage for the first time then it updates the data, but after 10 seconds if I refresh the page it does't update the data. But if I keep refreshing it for 10 seconds then it works.
So could you please tell me how to get it update the data without having to keep on browsing the pages or refreshing the home page?
Thanks :)
function __construct() {
parent::__construct();
// Visitor Counter
if (!$this->session->userdata('timeout')) {
$out = time() + 10; // I will change it to $out = time() + 60*60; later
$this->session->set_userdata('timeout', $out);
mysql_query("UPDATE cane_visitor_counter SET visitor_stat = visitor_stat+1
WHERE id = '1'");
} else {
$timeout_time = $this->session->userdata('timeout');
if (time() > $timeout_time) {
$this->session->set_userdata(array('timeout' => ''));
$this->session->sess_destroy();
}
}
}
edit
What I am trying to achieve is when an user visits the webpage for the first time, I want to update my database. Within 10 seconds (for example purpose), if the visitor again visits the home page, the database will not be updated. But after 10 seconds if he again visits the home page, I want to update my database.
Thanks :)
Your code says "if there is no timeout in the session, update the count". You want it to say "if there is no timeout in the session, or there is but it's old, update the count".
function __construct() {
parent::__construct();
// Visitor Counter
if (!$this->session->userdata('timeout') || $this->session->userdata('timeout') < time()) {
$this->session->set_userdata('timeout', time() + 10);
mysql_query("UPDATE cane_visitor_counter SET visitor_stat = visitor_stat + 1 WHERE id = 1");
}
}
I'm not a CodeIgniter user, so I am assuming that you used its session facilities correctly; I just used them the same way.
I am creating a session when a user logs in like so:
$_SESSION['id'] = $id;
How can I specify a timeout on that session of X minutes and then have it perform a function or a page redirect once it has reached X minutes??
EDIT: I forgot to mention that I need the session to timeout due to inactivity.
first, store the last time the user made a request
<?php
$_SESSION['timeout'] = time();
?>
in subsequent request, check how long ago they made their previous request (10 minutes in this example)
<?php
if ($_SESSION['timeout'] + 10 * 60 < time()) {
// session timed out
} else {
// session ok
}
?>
When the session expires the data is no longer present, so something like
if (!isset($_SESSION['id'])) {
header("Location: destination.php");
exit;
}
will redirect whenever the session is no longer active.
You can set how long the session cookie is alive using session.cookie_lifetime
ini_set("session.cookie_lifetime","3600"); //an hour
EDIT: If you are timing sessions out due to security concern (instead of convenience,) use the accepted answer, as the comments below show, this is controlled by the client and thus not secure. I never thought of this as a security measure.
Just check first the session is not already created and if not create one. Here i am setting it for 1 minute only.
<?php
if(!isset($_SESSION["timeout"])){
$_SESSION['timeout'] = time();
};
$st = $_SESSION['timeout'] + 60; //session time is 1 minute
?>
<?php
if(time() < $st){
echo 'Session will last 1 minute';
}
?>
<script type="text/javascript">
window.setTimeout("location=('timeout_session.htm');",900000);
</script>
In the header of every page has been working for me during site tests(the site is not yet in production). The HTML page it falls to ends the session and just informs the user of the need to log in again. This seems an easier way than playing with PHP logic.
I'd love some comments on the idea. Any traps I havent seen in it ?
<?php
session_start();
if (time()<$_SESSION['time']+10){
$_SESSION['time'] = time();
echo "welcome old user";
}
else{
session_destroy();
session_start();
$_SESSION['time'] = time();
echo "welcome new user";
}
?>
Byterbit solution is problematic because:
having the client control expiration of a server side cookie is a security issue.
if expiration timeout set on server side is smaller than the timeout set on client side, the page would not reflect the actual state of the cookie.
even if for the sake of comfort in development stage, this is a problem because it won't reflect the right behaviour (in timing) on release stage.
for cookies, setting expiration via session.cookie_lifetime is the right solution design-wise and security-wise! for expiring the session, you can use session.gc_maxlifetime.
expiring the cookies by calling session_destroy might yield unpredictable results because they might have already been expired.
making the change in php.ini is also a valid solution but it makes the expiration global for the entire domain which might not be what you really want - some pages might choose to keep some cookies more than others.
session_cache_expire( 20 );
session_start(); // NEVER FORGET TO START THE SESSION!!!
$inactive = 1200; //20 minutes *60
if(isset($_SESSION['start']) ) {
$session_life = time() - $_SESSION['start'];
if($session_life > $inactive){
header("Location: user_logout.php");
}
}
$_SESSION['start'] = time();
if($_SESSION['valid_user'] != true){
header('Location: ../....php');
}else{
source: http://www.daniweb.com/web-development/php/threads/124500
<?php
session_start();
if($_SESSION['login'] != 'ok')
header('location: /dashboard.php?login=0');
if(isset($_SESSION['last-activity']) && time() - $_SESSION['last-activity'] > 600) {
// session inactive more than 10 min
header('location: /logout.php?timeout=1');
}
$_SESSION['last-activity'] = time(); // update last activity time stamp
if(time() - $_SESSION['created'] > 600) {
// session started more than 10 min ago
session_regenerate_id(true); // change session id and invalidate old session
$_SESSION['created'] = time(); // update creation time
}
?>
I have a site where a user submits a message using AJAX to a file called like.php. In this file the users message is submitted to a database and it then sends a link back to the user. In my Javascript code I disabled the text box the user types into when they submit the AJAX request.
The only problem is, a malicious user can just constantly send POST requests to like.php and flood my database. So I would like to implement simple flood protection.
I don't really want the hassle of another database table logging users IPs and such... as if they are flooding my site there will be a lot of database read/writes slowing it down. I thought about using sessions, like have a session that contains a timestamp that gets checked every time they send data to like.php, and if the current time is before the timestamp let them add data to the database, otherwise send out an error and block them. If they are allowed to enter something into the database, update their session with a new timestamp.
What do you think? Would this be the best way to go about it or are there easier alternatives?
Thanks for any help. :)
Session is the easiest to do this, and has the least overhead as well. You can store two bits of data in the session, timestamp of last post, and the ip the post is comming from. Here is how you check legitimacy then:
session_start();
if(isset($_SESSION['ip']) && $_SESSION['last_post'] + MININTERVAL < time()) die('too early');
$_SESSION['last_post'] = time();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
// store the message
Use a token. You generate the token and add it to the page originating the request. In like.php you verify that the request contains a valid token, which means it comes from your page instead of an external one POSTing directly.
You don't need to go through the whole record file. Instead:
<?php
define("FLOODPOOL", ".");
define("FLOODPOOL_LIMIT", 30);
define("FLOODPOOL_DURATION", 60 * 60 * 24);
define("FLOODPOOL_AUTOCLEAN", true);
// Record and check flood.
// Return true for hit.
function floodpool_check($id){
$fp = fopen(FLOODPOOL . DIRECTORY_SEPARATOR . 'fp_' . basename($id), 'a+');
fwrite($fp, pack('L', time()));
if(fseek($fp, -4 * FLOODPOOL_LIMIT, SEEK_END) === -1) {
return false;
}
$time = reset(unpack('L', fread($fp, 4)));
fclose($fp);
if(time() - $time < FLOODPOOL_DURATION) {
if(FLOODPOOL_AUTOCLEAN){
#floodpool_clean();
}
return true;
}
return false;
}
// Clean the pool.
function floodpool_clean(){
$handle = opendir(FLOODPOOL);
while(false!==($entry=readdir($handle))){
$filename = FLOODPOOL . DIRECTORY_SEPARATOR . $entry;
if(time() - filectime($filename) > FLOODPOOL_DURATION && substr($entry, 0, 3) === 'fp_'){
unlink($filename);
}
}
closedir($handle);
}
Usage example:
if(floodpool_check($_SERVER['REMOTE_ADDR'])){
header("HTTP/1.1 429 Too Many Requests");
exit("Hit some *");
}
Another way to do this is to write a hidden form input to the page (that calls like.php) using jQuery. A bot won't be using javascript so your hidden form field won't exist.
Check for the hidden field (assign it a value and a name) and if it exists, then hit the database with the request.
Another way; code a hidden element into the page (<input style='display:none;' name='nospam' value='' />). A bot will auto-fill every field in the form, so you just check if this field is populated - a user can't see it so you know it's a bot if you've got content there.
Set the style (display:none;) using jQuery tho... again, a bot won't see the jQuery, so it will think this is a legit form input.
You may want to specify a 'this page requires javascript to run' notice somewhere for the user. Some alternative suggestions. After all - you said 'simple' ;)
Well I made a script to handle it for core requests only (no session requests or other requests who aren't calling the core). If you have a look to google you'll find scripts/classes which will kill your server because of high loads every time. The fact, that many use SESSIONs and maybe ALSO SQL/Database will let you get a flooding protection as a server-killer. Also the fact that SESSIONs need a Cookie (or a GET SID) so you can manipulate SESSIONs easy to get a new SESSION ID.
My function is text-based and do a simple handling. The bad thing is that you maybe have to use a CronJob to delete ips from time to time. Comparing to other scripts its about 10* faster (and more save than sessions).
I don't know if its really useful at all. ;)
You maybe like to change the rpm value to less or/and also the 200 req. My setting is a ban for a bot doing interval requests in <=6 seconds.
<?php
function ht_request_limiter() {
if (!isset($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
if (empty($_SERVER['REMOTE_ADDR'])) { return; } // Maybe its impossible, however we check it first
$path = '/your/path/ipsec/'; // I use a function to validate a path first and return if false...
$path = $path.$_SERVER['REMOTE_ADDR'].'.txt'; // Real file path (filename = <ip>.txt)
$now = time(); // Current timestamp
if (!file_exists($path)) { // If first request or new request after 1 hour / 24 hour ban, new file with <timestamp>|<counter>
if ($handle = fopen($path, 'w+')) {
if (fwrite($handle, $now.'|0')) { chmod($path, 0700); } // Chmod to prevent access via web
fclose($handle);
}
}
else if (($content = file_get_contents($path)) !== false) { // Load existing file
$content = explode('|',$content); // Create paraset [0] -> timestamp [1] -> counter
$diff = (int)$now-(int)$content[0]; // Time difference in seconds from first request to now
if ($content[1] == 'ban') { // If [1] = ban we check if it was less than 24 hours and die if so
if ($diff>86400) { unlink($path); } // 24 hours in seconds.. if more delete ip file
else {
header("HTTP/1.1 503 Service Unavailable");
exit("Your IP is banned for 24 hours, because of too many requests.");
}
}
else if ($diff>3600) { unlink($path); } // If first request was more than 1 hour, new ip file
else {
$current = ((int)$content[1])+1; // Counter + 1
if ($current>200) { // We check rpm (request per minute) after 200 request to get a good ~value
$rpm = ($current/($diff/60));
if ($rpm>10) { // If there was more than 10 rpm -> ban (if you have a request all 5 secs. you will be banned after ~17 minutes)
if ($handle = fopen($path, 'w+')) {
fwrite($handle, $content[0].'|ban');
fclose($handle);
// Maybe you like to log the ip once -> die after next request
}
return;
}
}
if ($handle = fopen($path, 'w+')) { // else write counter
fwrite($handle, $content[0].'|'.$current .'');
fclose($handle);
}
}
}
}
Edit: My way to test the request time was with microtime and simulate 10'000 users. I ask google and tested (as example) http://technitip.net/simple-php-flood-protection-class
So I don't know what should be simple there? You have about 3 SQL Requests at one time like:
$this -> user_in_db($ip))
$this->user_flooding($ip);
$this->remove_old_users();
It maybe supply more functions, but all legit users use servertime for nothing. ;)
If you want to stop flooding a search page you can try it like this way:
$flood_protection_interval = 2;
session_start();
if(
isset($_SESSION['ip']) &&
$_SESSION['counter'] > 10 &&
$_SESSION['last_post'] + $flood_protection_interval > time()
){
// $_SESSION['counter'] = 0; // Use this if you want to reset counter
die("<pre>\n\n\n\t<b>FLOOD PROTECTION</b>");
}
$_SESSION['counter']++;
$_SESSION['last_post'] = time();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
So if your visitor search 10 times under e.g. 2 seconds he will be stopped!
I thought about using sessions, like
have a session that contains a
timestamp that gets checked every time
they send data to like.php
This won't stop bots as they can receive and send the same cookies that users do.
You should really have users logging into such a system. Seems to be worth protecting access. You could also consider limiting posts per minute per ip but multiple bots could still send many spam messages.
If you don't want to implement a login then many sites use captcha to try and cut down on such attempts.
http://www.phpcaptcha.org/