O token de formulário exclusivo desabilita a multitarefa para o usuário

Se eu quiser proteger o meu site e os usuários dos ataques Cross Site Falsa (CSRF), posso gerar um token exclusivo $token = md5( time() * rand ); em cada página que tenha um formulário. O token é enviado em um campo de input oculto echo ''; e ao mesmo tempo armazenado em uma variável de session $_SESSION['token'] = $token; .

Vou verificar se em qualquer formulário enviado if($_POST['token'] == $_SESSION['token']) e proceder em conformidade.

No entanto, alguns usuários podem ser multitarefa. Isso é algo que eu realmente estou fazendo agora, enquanto eu estou postando isso.

Ao compor minha publicação, eu abrir diferentes janelas / abas para possivelmente pesquisar informações ou examinar algumas outras questões sobre o excesso de pilha. O estouro da pilha me permite enviar o formulário sem problemas.

Mas se eu fizesse isso no meu site fazendo isso – ou seja, procure outras páginas enquanto ainda compõe uma postagem / formulário – meu $token seria regenerado cada vez que eu retirar uma página diferente do meu site. Fazendo o token de input oculto no formulário em que estou trabalhando e, eventualmente, quero enviar incorreto , porque não corresponde mais à $_SESSION['token'] , que foi regenerada quando visitei uma página diferente …

Quaisquer boas ideias sobre como evitar esta questão, ou quaisquer soluções melhores para parar a CSRF em primeiro lugar?

Quero permitir que meus usuários façam tarefas múltiplas e desejam ser protegidas contra CSRF …

Eu tive o mesmo problema com o que você afirma por causa de CSRF único e é substituído a menos que eles enviem a página mais recente, mas se você usar uma matriz w / session, ele deve resolver seu (s) problema (s). Além disso, você pode querer include um captcha, eu recomendaria o Recaptcha do Google.

 session_start(); function createToken(){ $token = sha1(uniqid(mt_rand(), true)); $_SESSION['Tokens']['Token'][] = $token; $_SESSION['Tokens']['Time'][] = time() + (10 * 60); #10 min limit #you can omit/change this if you want to not limit or extend time limit return $token; } function checkToken($token){ clearTokens(); foreach($_SESSION['Tokens']['Token'] as $key => $value){ if($value === $token){ return true; } } return false; } function clearTokens(){ foreach($_SESSION['Tokens']['Time'] as $key => $value){ if($value <= time()){ unset($_SESSION['Tokens']['Token'][$key], $_SESSION['Tokens']['Time'][$key]); #remove last parameter if you aren't using token time limit } } } 

seu HTML:

  

Chefe do Token PHP

 if(isset($_POST['token']) && checkToken($_POST['token'])){ #valid token }else{ #create error message saying that they tried to repost data or session token expired } 

O navegador deve manter o ID da session correto, mesmo entre guias e janelas, o ID da session deve ser o mesmo. (o pressuposto perigoso deve ser testado através do navegador para ter certeza)

gere mais tokens que devem ser válidos com base no ID da session.

então você poderia verificar algo assim.

 $tokenCorrect = false; foreach($_SESSION['tokens'] as $token) { if ($token !== $_POST['token']) continue; $tokenCorrect = true; } if ($tokenCorrect == false) { die(); // // Maybe log to database ?? but watch if possible Denial of Service because somebody can write your disk/ shared diskspace full with only making fast requests with a invalid CSRF token }