2012-02-23 5 views
0

원하는 작업입니다.양식 제출이 포함 된 고유 토큰이 작동하지 않는 것 같습니다.

사용자가 고유 토큰을 사용하여 양식을 두 번 제출하지 못하도록합니다. 여기에 올바른 코드가 있다고 생각하지만 여전히 작동하지 않습니다. 양식을 처음 제출할 때 출력은 "두 번 보내지 마십시오"입니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

<?php session_start(); ?> 
<html> 
<body> 

<?php 

$_SESSION['token'] = md5(session_id() . time()); 
?> 

<?php 
if (isset($_SESSION['token'])) 
{ 
if (isset($_POST['token'])) 
{ 
    if ($_POST['token'] != $_SESSION['token']) 
    { 
     echo "Don't send twice!"; 
    } 
} 
} 
else { 

echo "Thank you for submitting"; 

} 

?> 

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> 
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" /> 
<input type="text" name="bar" /> 
<input type="submit" value="Save" /> 
</form> 
if(isset($_SESSION['token']))에 대한 조건이 항상 충족되기 때문에 Thank you for submitting 당신이 토큰을 생성하고이 바로 위에 세션 변수를 설정하기 때문에 절하면 ... 그것도이다, 표시되지 않습니다

+2

모든 페이지가로드 될 때마다 $ _SESSION [ 'token']을 새로 작성하므로 "time()"값이 계속 변경됩니다. 따라서 조건이 항상 충족됩니다. – rlanvin

+0

양식 재 제출을 방지하기 위해 양식을 제출 한 후 동일한 페이지로 리디렉션 –

+0

@ Rémi 토큰을 변경했습니다 ... $ _SESSION [ 'token'] = md5 (uniqid()); ...하지만 여전히 똑같은 문제가 있는데 처음 제출할 때 "두 번 보내지 마라."라고 말합니다. 몇 가지 코드 예제를 보여줄 수 있습니까? – user1009453

답변

1

왜 것 처음 제출 한 후에는 항상 "두 번 보내지 마십시오"를보십시오. 토큰을 생성하는 폼을로드 할 때 토큰을 세션에 저장하고 폼에 저장하십시오. 양식을 제출 한 후 위로부터 스크립트를 다시 시작하십시오. 토큰이 이제 post 변수에 있습니다. 하지만 세션 토큰을 다시 만듭니다. 게시물과 세션을 비교합니다. 물론 지금은 새로운 토큰을 생성 했으므로 일치하지 않습니다. 물론 그들은 동일하지 않습니다.

나는 당신의 코드를이 구조를 권장합니다 여기

<html> 
<body> 
<?php 
session_start(); 

//HAS THE FORM BEEN SUBMITTED? 
if(isset($_POST)) 
{ 
    //THE FORM HAS BEEN SUBMITTED 

    //VALIDATE THE TOKEN 
    if($_POST['token'] == $_SESSION['token']) 
    { 
     //THE TOKEN WAS VALID, CONTINUE WITH PROCEDURES 

    } 
    else 
    { 
     echo 'Invalid token, please try again!'; 
    } 

} 
else 
{ 
    //FORM NOT SUBMITTED YET 

    $token = $_SESSION['token'] = md5(session_id() . time(). rand()); 
    //i recommend adding rand() otherwise there is always a 1 second window in which the token could be doubled up... 

    echo '<form action="'. $_SERVER['PHP_SELF'] .'" method="post">'; 
    echo '<input type="hidden" name="token" value="'. $token .'" />'; 
    echo '<input type="text" name="bar" />'; 
    echo '<input type="submit" value="Save" />'; 
    echo '</form>'; 
} 
?> 
</body> 
</html> 
1

개념은 결함이있다.

  1. 브라우저는 사용자가 POST를 사용하여 양식을 두 번 제출하도록 허용하지 않습니다. 그들은 양식을 두 번 제출하는 위험에 대해 사용자에게 경고합니다.

  2. 사용자가 양식을 두 번로드하는 경우이 스크립트는 두 양식에서 토큰이 다르기 때문에 두 번의 제출을 ​​피할 수 없습니다.

제출을 데이터베이스에 저장하는 것이 좋습니다. 이렇게하면 동일한 세션 (또는 동일한 사용자)이 하나의 레코드 만 저장할 수 있습니다.

+1

매우 유효한 포인트입니다! 정말로 두 번 제출하지 않는다고 확신하는 경우 토큰이 도움이되지 않습니다. CSRF로부터 자신을 보호하기 위해 양식 토큰을 사용하는 것이 좋습니다. – olli

관련 문제