I have a php script that sends an activation link via email to the users so they can activate their account. The link is like this: mysite.com/activation.phpid?id=20
How can I create the link to expire after 24 hours?
I haven't tried anything as I couldn't find anything to teach me how to do it. all I know is that I might be able to do this by storing something in mysql but how?
it will be great if someone could tell me the step by step instruction please.
Thanks
Make the link like this:
$time = time();
$hash = md5($id . $time . "somerandomsalt"); // check this again in activation.php
$link = "activation.php?id=" . $id . "&hash=" . $hash . "&time=" . $time;
Then in activation.php you check if the hash matches. Oh, and check the time of course :P
You could obfuscate it a bit to hide the id, hash and time query parameters, but this is the basics.
Just add an extra field in your database with the expiration date of the link. When the link is clicked you can then check the date to make sure it isn't expired.
edit
I'm guessing at your column and table names.
SELECT IF (DATEDIFF(date_registered, CURRENT_TIMESTAMP) <= 0, 1, 0) AS expired
FROM users
WHERE id = 20
If expired is 1 then the link is expired. If it is 0 then it is valid.
Related
I'm writing an hour registration system for my projectteam at school. Everything is pretty much working, but I can't seem to get the validation of user rights to work.
Validation is done in the acctype field within the user table. If 0 (guest), you can only view the list of hours, if 1 (specialist) you can add your own hours and if 2 (project-manager), you can review the hours users have submitted.
At first I was only using the $account query but instead of selecting them all I selected acctype only.
Does anyone have any idea what am I doing wrong?
$cookie = $_COOKIE['user'];
$account = mysqli_query($conn, "SELECT * FROM user WHERE user = '" . $cookie . "'");
$acctype = mysqli_fetch_assoc($account->acctype);
if(isset($cookie) && $acctype >= 1) {
} else {
}
Jonathan
I believe there's a few things wrong here:
You're reading the cookie before checking if it's set. That's a mistake. You should see if there's a cookie, and THEN read it in. You also don't need to assign it a separate variable.
Note: As I said in my comment, user data should be in a session, not a cookie.
I don't know what your DB schema looks like, but your query is SELECT * FROM user, meaning that if you have an ID, a user name, an access level, and some other things, you're going to get ALL that into the var $acctype, which obviously isn't an integer.
I think the fix is to execute your query, get your results, and then compare the row(s) returned and only check the acctype part:
if ($row['acctype'] >= 1){
}
Documentation: http://us1.php.net/mysqli_fetch_assoc
Could anyone tell me why this doesn't work? In my database lastactive is 2013-12-10 16:15:12, updates every time a user refreshes any page on my website.
I select it and set it as a variable:
$lastactive = $row[5];
Here's where I thought it should work, but doesn't. Using 10 seconds for testing.
if(time() > $lastactive+10){
print('<div id="user_online_status" style="color: #aaa;">[OFFLINE]</div>');
}
else if(time() < $lastactive+10){
print('<div id="user_online_status">[ONLINE]</div>');
}
You're comparing a unix timestamp to a MySQL datetime string. You need to convert it to a unix timestamp before comparing the two:
$lastactive = strtotime($row[5]);
Replace your SELECT statement from:
SELECT lastOnline FROM user
to something like...
SELECT UNIX_TIMESTAMP(lastOnline) FROM user
that's it. You're currently checking the Date string against a UNIX Timestamp.
I dont see its good idea to check for time.
What if user doesnt refresh the page , he let the page open and went to eat ? . he will be loggedout? it will be anonying.
I guess better is to use unload
$(window).unload(function() {
// Send an Ajax request to logout.php
});
if user doesnt refresh the page, you can check it on server using cron.
$limit = $userOnline+60; // cron set to run every minute
if($userOnline < $limit)
$userStatus = "offline";
else
$userStatus = "online";
so im trying to have a table that shows which users are online on my site I have everything working besides the part where if someone closes the site without logging out first they stay on the table as logged in. i'll try to eplain my situation the best I can.
in my database I have a users table in that table is online when you login your online status is set to 1, when you click logout online is set to 0. here is the code im trying to use so that if someone is inactive for 10minutes they will be logged out ( online set to 0 )
<?php
session_start();
$timeout = 10; // Set timeout minutes
$logout_redirect_url = "logout.php"; // Set logout URL
$timeout = $timeout * 60; // Converts minutes to seconds
if (isset($_SESSION['last_activity'])) {
$elapsed_time = time() - $_SESSION['last_activity'];
if ($elapsed_time >= $timeout) {
mysql_query("UPDATE users SET online = 0 WHERE username = '".$_SESSION['username']."'")
or die(mysql_error());
session_destroy();
header("Location: $logout_redirect_url");
}
}
$_SESSION['last_activity'] = time();
?>
This works fine it logs them out if they wait the 10minutes, but if they just close the browser it keeps online = 1 which displays them on the list.
I believe the problem is that when they close the browser that destroys the session before it gets the chance to update the users online and set it to 0
is there anyway around this? help would be very much appreciated thanks :)
btw I know not to use mysql anymore and everything, I will try to switch to something else once I learn more and get everything working first.
The underlying problem is that when a user closes their browser, there's no reliable way to first communicate with your server. [There are things you could try, but in my opinion that's a rabbit hole you shouldn't go down] All you really "know" is how recently the user visited your site logged-in. (in your case $_SESSION['last_activity']).
At a basic level, you will want to start persisting that information in your database, and then have a process kicked off occasionally to cleanup stale sessions.
e.g.
//On page load with a logged-in user
mysql_query("UPDATE `users`
SET `last_activity` = '" . time() . "'
WHERE `username` = '" . mysql_real_escape_string($_SESSION['username']) . "'");
note that assumes you've added an INT column to your table named last_activity
and then in a process that executes, say, every 15 minutes:
mysql_query("UPDATE `users`
SET `online` = 0
WHERE `last_activity` < '" . strtotime('-30 minutes') . "'");
Unix servers have something called cron especially for period tasks/scripts, so that's what I would recommend for kicking off your cleanup script.
I was wondering if there was any other way to keep users logged in when they revisit my website even though the session has expired.
I currently use a cookie based method, but I was wondering if there were other methods people are using.
No, there are no [reliable] methods beside a cookie.
There are other methods, but you should refrain from using them because they in no way are as reliable as cookies.
You can use a IP based login system. If using this, you will see issues with multiple users from same IP.
You can generate a special link for users that is uniquely generated and make a login based on that
Instead of worrying about doing it another way, you should work on making your cookie-using system more secure.
This is a very old question, but for the sake of future visitors, I would like to supply an answer.
You SHOULD use cookies. Like the other answers have noted, they are the most reliable method out there. If you want to make sure the user isn't visiting with an expired cookie, write the time at which it expires as a cookie with a checksum.
Here's an example using PHP:
$expireTime = time() + (60*60*24*3); // 3 days ( 60 seconds * 60 minutes * 24 hours * 3 days )
$rawPepper = openssl_random_pseudo_bytes(16);
$hexPepper = bin2hex($rawPepper);
setCookie($cookieKey, $cookieValue, $expireTime);
setCookie("expiresWhen", $expireTime, $expireTime);
setCookie("rand", $hexPepper, $expireTime);
$hash_1 = hash('sha512', "Your_Super_Secret_Salt" . $cookieValue . "Another_Super_Secret_Salt!" . $expireTime);
$hash_2 = hash('sha512', "Yet_Another_Salt!" . $hash_1. $hexPepper);
setCookie("checksum", $hash_2, $expireTime);
Then in your other PHP form for validation you say:
$expires = $_COOKIE['expiresWhen'];
$pepper = $_COOKIE['rand'];
$cookieVal = $_COOKIE[$cookieKey];
$givenCheckSum = $_COOKIE['checksum'];
$hash_1 = hash('sha512', "Your_Super_Secret_Salt" . $cookieVal . "Another_Super_Secret_Salt!" . $expires);
$correctCheckSum = hash('sha512', "Yet_Another_Salt!" . $hash_1. $pepper)
if($givenCheckSum != $correctCheckSum){
/* user's cookie has expired. Handle as you please */
}else{
/* Cookie is still valid */
}
Anyone care to make corrections to this or supply suggestions?
I am trying to create a forgot password feature which will expire the link created after x hours. So I am storing time() data in database value when a user requests a password reset. So how can I expire it?
three options:
compare the time you saved on the db with the one you get when the user click the link
Use a cron job and make it run periodically
Just don't save in the db and make the link to care about everything. You could use a signature + a salt to avoid users to modify this link
like:
$now = time();
$sk = sh1($user_id . $now . "yoursupersalthere")
$link = "http://www.example.com/forgot.php?id={$user_id}&ts={$now}&sk={$sk}"
that will be the link you sent to the user. Then to make the check
$ts = $_GET['ts'];
$user = $_GET['id'];
$sk = $_GET['sk'];
if (!$sk == sh1($user_id . $now . "yoursupersalthere")) {
die("bad signature");
}
elseif (time() - $ts > 3600 /* or put your expiration limit */) {
die('link expired');
}
// do your job
You're probably having a table entry with a reset link, just add a date field to it, and then either include a WHERE expiredate<NOW() or clean the table from time to time with a simple DELETE from table WHERE expiredata<NOW().
One method of doing this is to check to see if the link is expired when the link is clicked -- some pseudo-code:
// when the link is clicked pull the information from the database and get the time
// SQL goes here
// this will give you the difference in seconds
$diff = time() - $timestamp_from_db;
// we'll pretend the time expires in 8 hours
$expires_in = 8 * 60 * 60;
// for this example we'll pretend the expiration is 8 hours
if($diff <= $expires_in)
{
// has not been more then 8 hours
}
else
{
// has been more then 8 hours
}
The best way to do this that keeps the table clean is to implement the following:
The table needs at least the account ID with a UNIQUE index and foreign key to the accounts table, the hash with a UNIQUE index and a timestamp.
In the page that creates the link, do not allow "reset my password" based on information that can be obtained by a random person. If you do this, one can fill your table with reset password requests and generate spam and security concerns with your users.
In the page where the link is verified first delete all expired records by comparing NOW() with the stored timestamp, then simply SELECT using WHERE='$hash' (of course, you sanitize $hash). Given the UNIQUE index on the hash, this can only return one row or no rows.
The UNIQUE index on the account ID ensures that people cannot request multiple resets within the expiration time.