Skip to content

Instantly share code, notes, and snippets.

@CNG
Created February 5, 2013 05:48
Show Gist options
  • Save CNG/4712514 to your computer and use it in GitHub Desktop.
Save CNG/4712514 to your computer and use it in GitHub Desktop.
First whack at a single PHP file to both generate random keys and check if they are expired, while updating the expiration date every time they are checked. This allows generating a key and making it expire if unused too long.
<?php
/*
USAGE:
To request a new token: ?newtoken=please
To ask if token is valid: ?token=xamBVbmRlKcSSVsrxt8WEqQ6NdpS7z
SETUP:
$tokensFilename must be writable by script, preferably in a location outside
the web root
DEVELOPMENT NOTES:
This set of functions could be more streamlined. Part of this is due to
changing the token strategy midway, but it works as is, so in the interest
of not spending more time refactoring and testing, I'll leave it.
*/
// Filename where tokens are stored
$tokensFilename = 'tokens.txt';
// Maximum token age in seconds
$maxAge = 3600;
// Received token for validating
$token = isset($_REQUEST['token']) ? preg_replace('/[^-_a-zA-Z0-9]/', '', $_REQUEST['token']) : FALSE;
// Requesting new token
$needNewToken = isset($_REQUEST['newtoken']) && !strcmp($_REQUEST['newtoken'],'please');
/*
* Given optional string length
* Returns random string
*/
function randomString($length = 30) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
/*
* Given filename where tokens stored
* Returns array with tokens as keys and timestamps as values
*/
function getAllTokens($filename){
$rawcontents = explode("\n",file_get_contents($filename));
foreach ($rawcontents as $key => $value){
if (strlen($value) < 10){
unset($rawcontents[$key]);
}
}
$contents = array();
foreach($rawcontents as $line){
list($token, $timestamp) = explode("|",$line);
$contents[$token] = $timestamp;
}
unset($line);
return $contents;
}
/*
* Given array with tokens as keys and timestamps as values and filename
* Returns true on successful file write
*/
function setAllTokens($filename, $tokenInfo){
$contents = '';
foreach($tokenInfo as $token => $timestamp){
$contents .= "$token|$timestamp\n";
}
unset($token,$timestamp);
return file_put_contents($filename,$contents);
}
/*
* Given array with tokens as keys and timestamps as values and expiration duration in seconds
* Returns same array with expired tokens removed
*/
function validTokens($tokenInfo, $maxAge){
foreach($tokenInfo as $token => $timestamp){
if( time() - intval($timestamp) > $maxAge ){
unset($tokenInfo[$token]);
}
}
unset($token,$timestamp);
return $tokenInfo;
}
/*
* Given filename where tokens stored
* Returns new token after adding it to token list with timestamp
*/
function newToken($filename){
$token = randomString(30);
$timestamp = time();
$contents = file_get_contents($filename);
$contents .= "$token|$timestamp\n";
file_put_contents($filename,$contents);
return $token;
}
/*
* Given filename where tokens stored and token to search for
* Returns TRUE after timestamp successfully updated for token
*/
function renewToken($filename,$token){
$timestamp = time();
$tokens = getAllTokens($filename);
$tokens[$token] = $timestamp;
setAllTokens($filename,$tokens);
return TRUE;
}
/*
* Given filename where tokens stored and max token age in seconds
* Returns TRUE after removing expired tokens from file
*/
function cleanTokens($filename,$seconds){
$tokens = getAllTokens($filename);
setAllTokens($filename,validTokens($tokens,$seconds));
return TRUE;
}
/*
* Given filename where tokens stored, token to search for and max token age in seconds
* Returns TRUE if token is expired or FALSE otherwise
*/
function isTokenValid($filename,$token,$seconds){
cleanTokens($filename,$seconds);
$tokens = getAllTokens($filename);
if (isset($tokens[$token])){
renewToken($filename,$token);
return TRUE;
} else {
return FALSE;
}
}
header('Content-Type: text/plain; charset=utf-8');
if($needNewToken){
echo newToken($tokensFilename);
} else {
if($token === FALSE){
// PHP apparently passes the string but web server might not display
// So we'll echo as well
$errmsg = 'Token not received';
header($errmsg, true, 404);
echo $errmsg;
} else {
if(isTokenValid($tokensFilename,$token,$maxAge)){
echo 1;
} else {
echo 0;
}
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment