2010-07-13 23 views
2

這篇文章的PHP形式的擔保:如何製作「Spinner」以改善php表單的安全性?

http://nedbatchelder.com/text/stopbots.html

...提到了「微調」爲:

的微調使用隱藏域的 幾件事情:它哈希在一起一個 阻止 篡改和重播的值的數量,並用於 難以理解的字段名稱。微調器是一個 MD5哈希:

* The timestamp, 
* The client's IP address, 
* The entry id of the blog entry being commented on, and 
* A secret. 

表格中的字段名是隨機的所有 。它們是 實際名稱,微調器和祕密的散列。微調器獲得固定字段 名稱,但 表單上的所有其他字段(包括提交 按鈕)都使用散列字段名稱。

有沒有人有一個如何在包含表單和相關的PHP表單提交腳本的PHP頁面上實現此代碼示例?

我不想使用AJAX,只是PHP。

+1

這是安全的,雖然默默無聞,它不會阻止所有的蜘蛛。例如,這不會欺騙NTOSpider。 – rook 2010-07-13 16:14:16

回答

0

您可以實現如下:

On Page Submit: 
    <?php 
    $spinnerKey = 'spin'; 
    $spinner = $_POST[$spinnerKey]; 
    $values = array(); 

    foreach ($_POST as $key=>$value) 
    { 
     if ($key !== $spinnerKey) 
     { 
     $values[deHash($key, $spinner)] = $value; 
     } 
    } 
?> 

A 'deHash' example: 
<?php 

    # You have to define deHash based on your hash but it 
    # would look something like this: 
    var $_rainbowTable = array(); 
    var $_expectedKeys = array(); 

    function deHash($hashedkey, $spinner) 
    { 
     $rt = $this->getRainbowTable($spinner); 

     return isset($rt[$hashedKey]) 
      ? $rt[$hashedKey]) 
      : NULL; 
    } 

    function getRainbowTable($spinner) 
    { 
     if (count($this->_rainbowTable) > 0) 
      return $this->_rainbowTable; 

     foreach ($this->_expectedKeys as $key) 
     { 
      $this->_rainbowTable[hash($key, $spinner)] == $key; 
     } 

     return $this->_rainbowTable; 
    } 
    ?> 

雖然最終我沒有看到這是如何阻止機器人提交您的網頁 - 它只是停止人的「電子郵件/用戶名/密碼」,從工作記憶瀏覽器插件。

+0

如果您引用了逆向函數,那麼您就錯過了「哈希函數」這一點。我認爲你的意思是加密/解密。 – Slartibartfast 2010-07-13 05:00:28

+0

我使用可逆方式,就像你說密鑰可以從哈希函數中計算出來一樣。 deHash會使用從你的微調器的散列和期望的字段名稱生成的彩虹表,然後使用你的哈希鍵作爲該表中的查找來返回實際的密鑰,否則返回null。 – 2010-07-13 05:16:53

+0

查看我的更新示例。我糾正了這個術語,因爲我提到你的意思是加密/解密,因爲你談到了倒退。 – 2010-07-13 05:21:43

0

如果在頁面加載時使用隨機值創建會話會怎麼樣。 例如 $_SESSION['name_for_email'] = 'something_random';

然後輸入字段

<input type="text" 
name="<?php echo htmlspecialchars($_SESSION['name_for_email'], ENT_QUOTES, "UTF-8");?>" 
> 

似乎更好使用AJAX。訪客點擊發送,將所有數據傳遞給外部php,在外部php調用$_SESSION['name_for_email'],這樣就可以知道郵件的域名。

如果沒有ajax,那麼帖子和頁面會重新加載,但是會在頁面頂部新建$_SESSION['name_for_email']。所以處理輸入表單的php代碼必須在定義之前$_SESSION['name_for_email']

如果輸入字段很多,則必須使用多個會話。可能會更好一些簡化版本。

$_SESSION['name_for_email'] = 'something_random'; 

<input type="text" 
name="field1<?php echo htmlspecialchars($_SESSION['name_for_email'], ENT_QUOTES, "UTF-8");?>" 
> 

只需要記住,那是field1電子郵件,field2的名稱等。

但是......再想一想。主要的問題是,機器人不會有$_SESSION['name_for_email']或bot的價值將是不正確的。好的,機器人「看到」電子郵件,「類型」電子郵件。

如果用$_SESSION['name_for_email']定義一些隱藏字段,並在處理輸入前檢查$_SESSION['name_for_email']是否與隱藏的輸入字段相同,我想會是相同的效果。因爲,如果機器人會知道正確的隨機值,那麼輸入字段名稱也是正確的。