【php】php表單防止重復提交(防csrf漏洞)


這篇文章介紹的內容是關於php表單防止重復提交(防csrf漏洞) ,有着一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
Token淺談

Token,就是令牌,最大的特點就是隨機性,不可預測。一般黑客或軟件無法猜測出來。

那么,Token有什么作用?又是什么原理呢?

Token一般用在兩個地方——防止表單重復提交、anti csrf攻擊(跨站點請求偽造)。

兩者在原理上都是通過session token來實現的。當客戶端請求頁面時,服務器會生成一個隨機數Token,並且將Token放置到session當中,然后將Token發給客戶端(一般通過構造hidden表單)。下次客戶端提交請求時,Token會隨着表單一起提交到服務器端。

然后,如果應用於“anti csrf攻擊”,則服務器端會對Token值進行驗證,判斷是否和session中的Token值相等,若相等,則可以證明請求有效,不是偽造的。

不過,如果應用於“防止表單重復提交”,服務器端第一次驗證相同過后,會將澀session中的Token值更新下,若用戶重復提交,第二次的驗證判斷將失敗,因為用戶提交的表單中的Token沒變,但服務器端session中Token已經改變了。

上面的session應用相對安全,但也叫繁瑣,同時當多頁面多請求時,必須采用多Token同時生成的方法,這樣占用更多資源,執行效率會降低。因此,也可用cookie存儲驗證信息的方法來代替session Token。比如,應對“重復提交”時,當第一次提交后便把已經提交的信息寫到cookie中,當第二次提交時,由於cookie已經有提交記錄,因此第二次提交會失敗。

不過,cookie存儲有個致命弱點,如果cookie被劫持(xss攻擊很容易得到用戶cookie),那么又一次gameover。黑客將直接實現csrf攻擊。

1.首先防范xss攻擊

2.驗證referrer

3.重要cookie設置https only ,比如token

4.使用簽名,令牌

5.get只用於查詢信息

6.表單提交用post

7.謹慎使用跨腳本注入

所以,安全和高效相對的。具體問題具體對待吧。

 

php表單加入Token防止重復提交

原理在於生成一個隨機字符串放在session里,提交表單后來驗證這個字符串,可以做到防止他人自己寫form來欺騙提交,重復提交或者雙擊提交。

簡單的用php實現的代碼如下:

<?php

/*

* PHP簡單利用token防止表單重復提交

* 此處理方法純粹是為了給初學者參考

*/

session_start();

function set_token() {

  $_SESSION['token'] = md5(microtime(true));

}

function valid_token() {

  $return = $_REQUEST['token'] === $_SESSION['token'] ? true : false;

  set_token();

  return $return;

}

//如果token為空則生成一個token

if(!isset($_SESSION['token']) || $_SESSION['token']=='') {

  set_token();

}

if(isset($_POST['test'])){

  if(!valid_token()){

    echo "token error";

  }else{

    echo '成功提交,Value:'.$_POST['test'];

  }

}

?>

<form method="post" action="">

  <input type="hidden" name="token" value="<?php echo $_SESSION['token']?>">

  <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 (

    'Q',

    '@',

    '8',

    'y',

    '%',

    '^',

    '5',

    'Z',

    '(',

    'G',

    '_',

    'O',

    '`',

    'S',

    '-',

    'N',

    '<',

    'D',

    '{',

    '}',

    '[',

    ']',

    'h',

    ';',

    'W',

    '.',

    '/',

    '|',

    ':',

    '1',

    'E',

    'L',

    '4',

    '&',

    '6',

    '7',

    '#',

    '9',

    'a',

    'A',

    'b',

    'B',

    '~',

    'C',

    'd',

    '>',

    'e',

    '2',

    'f',

    'P',

    'g',

    ')',

    '?',

    'H',

    'i',

    'X',

    'U',

    'J',

    'k',

    'r',

    'l',

    '3',

    't',

    'M',

    'n',

    '=',

    'o',

    '+',

    'p',

    'F',

    'q',

    '!',

    'K',

    'R',

    's',

    'c',

    'm',

    'T',

    'v',

    'j',

    'u',

    'V',

    'w',

    ',',

    'x',

    'I',

    '$',

    'Y',

    'z',

    '*'

  );

  # Array indice friendly number of chars;

  $numChars = count($chars) - 1;

  $token = '';

  # 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 = '';

    # 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['token'] = $token;

?>

<form action="action.php" method="post"

<input type="hidden" name="token" value="<?=$token?>" />

<!-- 其他input submit之類的 -->

</form>

action.php

<?php

session_start();

if($_POST['token'] == $_SESSION['token']){

  unset($_SESSION['token']);

  echo "這是一個正常的提交請求";

}else{

  echo "這是一個非法的提交請求";

}

?>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM