Pregunta

I have got a problem, and I am unable to find any solution. The Problem is that When User Opens a Page, a Security Token is being generated like this and added to the SESSION Array

$token = generate_csrf_token();
$_SESSION['tokens'][] = $token;

I use this $token in the Form submission as hidden input for CSRF Security. Now, The Problem is, If User Post any comment I can delete the $token from the array after comment being posted like this

$token = $_POST['token'];

// comment posting process

$key = array_search($token, $_SESSION['tokens']);
unset($_SESSION['tokens'][$key]);

But If User Does not post any comment and quit the Page, How, I can Delete that $token from the $_SESSION['tokens'][] array. If I do not delete, this could cause of so many un-used $tokens in the array.

¿Fue útil?

Solución

In a normal situation, once a user quits a page his cookie refering to the session will be cleared. (when he closes his browser). The next time he opens a browser and visits your page, he will start a new session.

Now because he lost the reference to your session and nobody else is using it either, the session file will no longer be accessed and once it hasnt been access for a certain amount of time, the garbage collector will clear it.

So you do not need to worry about "Clearing security tokens" when a user leaves the page. That is automatically taken care of. Unless ofcourse you screwed with the session management yourself. See the session settings information for options you can change.

Now if your goal is to clear the tokens while the user is still on the page using the same session, there are a few options.

The first would be to use a single security token per session. If the user closes the page (read: loads another page on your site) then he will be issues a new token in $_SESSION['token'] (no array) and the old one is cleared. That does require you to check the token after a POST before you change it.

Another option is to only keep like the last 5 or so tokens. Then you can keep it clean without needing to alter the check for tokens. You can use array_shift to do that

<?
$tokens[] = 'new token';
if (count($tokens)>5) {
  array_shift($tokens); //first is removed, so the last 5 remain
}
?>

The last way I can think of is to add a time to the token and on page request, loop trough all tokens and check the time. If the time is more then xx minutes in the past, remove it.

Otros consejos

As with any asynchronous client-server state, the answer is timeouts. You cannot guarantee that a token will ever be used and even if it does get used eventually, you cannot know when. There's also no explicit feedback mechanism for unused tokens; unused tokens are simply never used.

As such, associate a timestamp with each token. Periodically you check all the stored tokens and remove the ones you deem expired. Choose a sensible expiration timeframe. E.g.:

// run garbage collection roughly every 100 page loads
if (mt_rand(0, 100) == 0) {
    foreach ($_SESSION['tokens'] as $i => $token) {
        if ($token['timestamp'] < time() - 3600) {
            unset($_SESSION['tokens'][$i]);
        }
    }
}

Since sessions expire all by themselves by the same mechanism eventually, maybe you can simply leave this up to the session expiring.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top