我的PHP表单Key类有问题

时间:2016-05-04 02:49:37

标签: php oop

我正在关注this tutorial以尝试制作PHP表单密钥验证脚本。出于某种原因,我的构造函数没有为我的$old_formKey变量创建值。

该教程提到单身人士更安全,但不会进入实施阶段。我知道使用Java的OOP的基本原则,但我对PHP OOP原则知之甚少。我只是试图通过使类变量静态来实现它 - 我认为这就是我的问题所在。但是,当我的构造函数被调用时,它应该给$old_formKey $_POST[form_key]的值,如果是isset()“

我无法让构造函数将旧formKey的值放在所需的变量空间中。

所以这就是我遇到问题的地方。

<?php
class formKey
{
    private static $formKey;

    private static $old_formKey;

    public function validate()
    {
        echo $_POST['form_key'];
        //We use the old formKey and not the new generated version
        if($_POST['form_key'] == $old_formKey) {
            //The key is valid, return true.
            return true;
        }
        else {
            //The key is invalid, return false.
            return false;
        }
    }
}
?>

我的formKey验证脚本看起来像这样。

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    //Validate the form key
    if(!isset($_POST['form_key']) || !$formKey->validate()) {
        //Form key is invalid, show an error
        $error_msg = 'Security Error.';
        $die = "die";
    }
    else {
        /*continue validation*/
    } 
}
?>

该脚本返回错误消息,然后显示它,因为$old_formKey方法中的validate()永远不会给出值。

出于某种原因,我无法在validate()方法中修改类变量。对不起,如果之前已经解决过。我老实地看着,找不到它!

function __construct()
{
    //We need the previous key so we store it
    if(isset($_SESSION['form_key']))
    {
        self::$old_formKey = $_SESSION['form_key'];
    }
}

抱歉,我忘了包含我的构造函数。它已在上面添加。

3 个答案:

答案 0 :(得分:1)

扩展formKey类?

class B extend formKey{
    public function validate($formKey, $oldFormKey)
    {
        return $formKey == $oldFormKey;
    }
}

像这样称呼它

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $oldFormKey = "abc";
    $formKey = new B();
    if (!isset($_POST['form_key']) 
        || !$formKey->validate($_POST['form_key'], $oldFormKey)) {
        //Form key is invalid, show an error
        $error_msg = 'Security Error.';
        $die = "die";
    } else {
        //continue validation 
    } 
}

它可能对您有用,而且,我很好奇&#34;出于某种原因,我无法在validate()方法中修改类变量&#34;

答案 1 :(得分:1)

要使变量通过对象(__construct()validate()),您需要在类范围内分配它们,然后从同一范围内调用它们:

class formKey
    {
        private $formKey,
                $old_formKey;

        public function __construct()
            {
                // I just set to false as default
                $this->old_formKey = false;
                // Assign here
                if(isset($_SESSION['form_key']))
                    $this->old_formKey = $_SESSION['form_key'];
            }

        public function validate()
            {
                // Use $this-> to recall it from the construct
                return ($_POST['form_key'] == $this->old_formKey);
            }
    }

答案 2 :(得分:0)

正如我已经写过评论,你提到的像 Dagon 所写的教程已经过时了,其次是完全虚假。

这与验证表单无关,关注此主题识别表单。

您生成一个由服务器生成的唯一标识符键(本例为PHP),以便跟踪表单状态。如果唯一的密钥发生变化,与服务器存储的密钥不同,则表单可能会在无法识别的情况下被拒绝(这并不意味着所有表格有效)。

本教程使用面向对象的方法,所以我会尊重它。正在制定以下步骤

  1. 生成一个唯一的密钥并将其存储在用户(或访问者,取决于此处的术语;我们将从现在开始将其描述为usersSESSION
  2. 以表格
  3. 输出
  4. 确定提交时的表单,并将(未识别的)密钥与存储在SESSION <中的(已识别的)密钥进行比较/ p>

    4.1。在满足身份时验证表单

    4.2。如果无法识别,则拒绝表格

  5. 从生成实例开始,类的布局非常简单,它不需要是singleton,也不应该包含任何静态

    该类的基础可以分为三个部分,创建存储识别

    class FormIdentifier {
    
      const CONTAINER_KEYSPACE = 'form_keys';
    
      /**
       * Generate a key
       * @return string
       */
      public function generateKey() {
        // you can use any complicated mumbo-jumbo to generate a key instead
        $key = uniqid();
        // store it
        $this->storeKey($key);
        // return for use, e.g. in a form
        return $key;
      }
    
      /**
       * Store a key into users session
       */
      protected function storeKey($key) {
        session_start();
          $_SESSION[self::CONTAINER_KEYSPACE][] = $key;
        session_write_close();
      }
    
      /**
       * Identifies a key against the keys in the users stored session.
       * @return true if identified, false otherwise
       */
      public function identifyKey($key) {
        session_start();
          if( ($found = search_array($key, $_SESSION[self::CONTAINER_KEYSPACE])) !== false ) {
            unset($_SESSION[self::CONTAINER_KEYSPACE][$found]);
            session_write_close();
            return true;
          } 
    
        session_write_close();
        return false;
      }
    }
    

    要生成密钥,我们不会将HTML输出与类和方法混合使用。 FormIdentifier的目的只是创建存储标识表单键,没有别的。这是一个在表单中使用的示例

    <form>
      <input type="hidden" name="form_key" value="<?php (new FormIdentifier)->generateKey() ?>" />
    </form>
    

    您也可以将返回的密钥存储在某处,并以不同的方式使用它,无论您需要什么样的套件。

    <?php $key = (new FormIdentifier)->generateKey(); ?>
    <input type="hidden" name="form_key" value="<?= $key ?>" />
    

    要识别(并最终验证)表单,您可以指定发布的表单 key ,并将其与存储在用户会话中的密钥进行比较。此处使用的结构最有可能向用户显示密钥不匹配的一些通知。它完全取决于您希望如何实现此步骤,您可以将其包装在函数中,甚至可以将其与类FormIdentifier结合使用。

    /**
     * Simple if/else, a POST was made so act on `form_key`s presence only
     */
    if($_POST && array_key_exists('form_key', $_POST)) {  
      if((new FormIdentifier)->identifyKey($_POST['form_key')) {
        // identity was verified  
        // validate your form
        $fv = new FormValidator($_POST);
        // or whatever ..
        $fv->validate();
      }
      else {
        // unable to determine identity
        // do something silly ..
      }
    }
    

    一些注释

    • 所提供的代码均未经过测试
    • 重要的是要认识到presentation logic应与此处所做的所有步骤分开。
    • 停止阅读较早 2年以上的教程!如果作者不介意更新它的东西,那么不要介意阅读它。