>  기사  >  백엔드 개발  >  반복 제출을 방지하기 위해 PHP 양식에 토큰을 추가하는 방법에 대한 분석

반복 제출을 방지하기 위해 PHP 양식에 토큰을 추가하는 방법에 대한 분석

高洛峰
高洛峰원래의
2016-12-20 15:52:00991검색

이 기사의 예에서는 반복 제출을 방지하기 위해 PHP 양식에 토큰을 추가하는 방법을 설명합니다. 참고할 수 있도록 모든 사람과 공유하세요. 세부 사항은 다음과 같습니다.

토큰에 대한 간략한 설명

토큰은 토큰이며 가장 큰 특징은 무작위성과 예측 불가능성입니다. 일반 해커나 소프트웨어는 이를 추측할 수 없습니다.

그렇다면 토큰의 기능은 무엇인가요? 원리는 무엇입니까?

토큰은 일반적으로 반복적인 양식 제출과 안티 csrf 공격(교차 사이트 요청 위조)을 방지하기 위해 두 가지 위치에서 사용됩니다.

둘 다 원칙적으로 세션 토큰을 통해 구현됩니다. 클라이언트가 페이지를 요청하면 서버는 임의의 숫자 토큰을 생성하고 세션에 토큰을 배치한 다음 클라이언트에 토큰을 보냅니다(보통 숨겨진 양식을 구성하여). 다음에 클라이언트가 요청을 제출하면 토큰이 양식과 함께 서버에 제출됩니다.

그런 다음 "anti csrf 공격"에 적용되면 서버는 토큰 값을 확인하여 세션의 토큰 값과 동일한지 확인합니다. 동일하면 요청이 유효한 것으로 증명할 수 있습니다. 위조되지 않았습니다.

단, "양식의 반복 제출 방지"를 위해 사용하는 경우 서버 측에서 첫 번째 검증이 동일한 후 사용자가 반복적으로 제출하면 세션의 Token 값이 업데이트됩니다. 두 번째 검증 판단은 사용자가 제출한 양식의 Token이 변경되지 않았지만 서버 측 세션의 Token이 변경되었기 때문에 실패한 것입니다.

위 세션 적용은 비교적 안전하지만 동시에 여러 페이지와 여러 요청이 있는 경우 여러 토큰을 동시에 생성하는 방법을 사용해야 합니다. 더 많은 리소스를 확보하고 실행 효율성을 감소시킵니다. 따라서 Session Token 대신에 쿠키에 인증정보를 저장하는 방식을 사용할 수도 있습니다. 예를 들어 "반복 제출"을 처리하는 경우 제출된 정보는 첫 번째 제출 후 쿠키에 기록됩니다. 두 번째로 제출하면 쿠키에 이미 제출 기록이 있으므로 두 번째 제출은 실패합니다.

그러나 쿠키 저장에는 치명적인 약점이 있습니다. 쿠키가 하이재킹되면(XSS 공격으로 사용자 쿠키를 쉽게 얻을 수 있음) 또 다른 게임 오버가 발생합니다. 해커는 CSRF 공격을 직접 구현합니다.

반복 제출을 방지하기 위해 PHP 양식에 토큰을 추가하는 방법에 대한 분석

따라서 안전성과 효율성은 상대적입니다. 구체적인 문제를 자세히 다루겠습니다.

반복 제출을 방지하기 위해 PHP 양식에 토큰이 추가됩니다

양식을 제출한 후 임의의 문자열을 생성하여 세션에 넣는 것이 원칙입니다. 다른 사람이 제출 내용을 속이기 위해 양식을 직접 작성하는 것을 방지하고, 다시 제출하거나 두 번 클릭하여 제출하세요.

반복 제출을 방지하기 위해 PHP 양식에 토큰을 추가하는 방법에 대한 분석

PHP에서 구현한 간단한 코드는 다음과 같습니다.

<?php
/*
* PHP简单利用token防止表单重复提交
* 此处理方法纯粹是为了给初学者参考
*/
session_start();
function set_token() {
  $_SESSION[&#39;token&#39;] = md5(microtime(true));
}
function valid_token() {
  $return = $_REQUEST[&#39;token&#39;] === $_SESSION[&#39;token&#39;] ? true : false;
  set_token();
  return $return;
}
//如果token为空则生成一个token
if(!isset($_SESSION[&#39;token&#39;]) || $_SESSION[&#39;token&#39;]==&#39;&#39;) {
  set_token();
}
if(isset($_POST[&#39;test&#39;])){
  if(!valid_token()){
    echo "token error";
  }else{
    echo &#39;成功提交,Value:&#39;.$_POST[&#39;test&#39;];
  }
}
?>
<form method="post" action="">
  <input type="hidden" name="token" value="<?php echo $_SESSION[&#39;token&#39;]?>">
  <input type="text" name="test" value="Default">
  <input type="submit" value="提交" />
</form>

위 방법이 더 간단하고, 다음 코드가 더 안전합니다.

Token.php

<?php
/*
 * Created on 2013-3-25
 *
 * To change the template for this generated file go to
 * Window - Preferences - PHPeclipse - PHP - Code Templates
 */
function getToken($len = 32, $md5 = true) {
  # Seed random number generator
  # Only needed for PHP versions prior to 4.2
  mt_srand((double) microtime() * 1000000);
  # Array of characters, adjust as desired
  $chars = array (
    &#39;Q&#39;,
    &#39;@&#39;,
    &#39;8&#39;,
    &#39;y&#39;,
    &#39;%&#39;,
    &#39;^&#39;,
    &#39;5&#39;,
    &#39;Z&#39;,
    &#39;(&#39;,
    &#39;G&#39;,
    &#39;_&#39;,
    &#39;O&#39;,
    &#39;`&#39;,
    &#39;S&#39;,
    &#39;-&#39;,
    &#39;N&#39;,
    &#39;<&#39;,
    &#39;D&#39;,
    &#39;{&#39;,
    &#39;}&#39;,
    &#39;[&#39;,
    &#39;]&#39;,
    &#39;h&#39;,
    &#39;;&#39;,
    &#39;W&#39;,
    &#39;.&#39;,
    &#39;/&#39;,
    &#39;|&#39;,
    &#39;:&#39;,
    &#39;1&#39;,
    &#39;E&#39;,
    &#39;L&#39;,
    &#39;4&#39;,
    &#39;&&#39;,
    &#39;6&#39;,
    &#39;7&#39;,
    &#39;#&#39;,
    &#39;9&#39;,
    &#39;a&#39;,
    &#39;A&#39;,
    &#39;b&#39;,
    &#39;B&#39;,
    &#39;~&#39;,
    &#39;C&#39;,
    &#39;d&#39;,
    &#39;>&#39;,
    &#39;e&#39;,
    &#39;2&#39;,
    &#39;f&#39;,
    &#39;P&#39;,
    &#39;g&#39;,
    &#39;)&#39;,
    &#39;?&#39;,
    &#39;H&#39;,
    &#39;i&#39;,
    &#39;X&#39;,
    &#39;U&#39;,
    &#39;J&#39;,
    &#39;k&#39;,
    &#39;r&#39;,
    &#39;l&#39;,
    &#39;3&#39;,
    &#39;t&#39;,
    &#39;M&#39;,
    &#39;n&#39;,
    &#39;=&#39;,
    &#39;o&#39;,
    &#39;+&#39;,
    &#39;p&#39;,
    &#39;F&#39;,
    &#39;q&#39;,
    &#39;!&#39;,
    &#39;K&#39;,
    &#39;R&#39;,
    &#39;s&#39;,
    &#39;c&#39;,
    &#39;m&#39;,
    &#39;T&#39;,
    &#39;v&#39;,
    &#39;j&#39;,
    &#39;u&#39;,
    &#39;V&#39;,
    &#39;w&#39;,
    &#39;,&#39;,
    &#39;x&#39;,
    &#39;I&#39;,
    &#39;$&#39;,
    &#39;Y&#39;,
    &#39;z&#39;,
    &#39;*&#39;
  );
  # Array indice friendly number of chars;
  $numChars = count($chars) - 1;
  $token = &#39;&#39;;
  # Create random token at the specified length
  for ($i = 0; $i < $len; $i++)
    $token .= $chars[mt_rand(0, $numChars)];
  # Should token be run through md5?
  if ($md5) {
    # Number of 32 char chunks
    $chunks = ceil(strlen($token) / 32);
    $md5token = &#39;&#39;;
    # Run each chunk through md5
    for ($i = 1; $i <= $chunks; $i++)
      $md5token .= md5(substr($token, $i * 32 - 32, 32));
    # Trim the token
    $token = substr($md5token, 0, $len);
  }
  return $token;
}
?>

form.php

<?php
include_once("token.php");
$token = getToken();
session_start();
$_SESSION[&#39;token&#39;] = $token;
?>
<form action="action.php" method="post"
<input type="hidden" name="token" value="<?=$token?>" />
<!-- 其他input submit之类的 -->
</form>

action.php

<?php
session_start();
if($_POST[&#39;token&#39;] == $_SESSION[&#39;token&#39;]){
  unset($_SESSION[&#39;token&#39;]);
  echo "这是一个正常的提交请求";
}else{
  echo "这是一个非法的提交请求";
}
?>

이 기사가 모든 사람에게 도움이 되기를 바랍니다. 그들의 PHP 프로그램 디자인이 도움이 됩니다.

반복 제출을 방지하기 위해 PHP 양식에 토큰을 추가하는 방법에 대한 자세한 분석을 보려면 PHP 중국어 웹사이트에서 관련 기사를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.