php令牌匹配不起作用

时间:2017-05-11 23:42:02

标签: php smarty token

我正在做表单验证器(使用令牌)。 Page基于smarty。所以在课堂文章中我有以下功能:

public static function getToken(){
		self::$token = md5(uniqid(rand(), TRUE));
		$_SESSION['token'] = self::$token;
	}

然后在.tpl文件中我插入了这样的值:

<input type="hidden" name="token" value="{Articles::$token}">

提交表单后,检查将在index.php中运行:

if(isset($_POST['token']) && $_POST['token'] == $_SESSION['token']){
	Articles::addComment($item, $_POST['name'], $_POST['email'], $_POST['comment']);
}

问题在于我获得了不同的令牌。例如,我回显了$_SESSION['token']并将其与表单中的值进行了比较(查看源代码)。 提交后,我试图回显值($_SESSION ['token']$_POST ['token]),它们也是不同的。显然,表格没有提交。

1 个答案:

答案 0 :(得分:0)

无需为用户以1:1的比例映射CSRF令牌。如果您在页面上有多个表单怎么办?如果用户打开了多个浏览器窗口会怎样?

定义要存储0..n令牌的内容,为它们设置合理的有效期,[可选]定义它们有效的。例如:

class Token {
    protected $id, $expiry;

    public function __construct($expiry=300, $id=NULL) {
        $this->expiry = time() + $expiry;
        if( is_null($id) ) {
            // actual secure ID generation.
            $this->id = bin2hex(random_bytes(32));
        } else {
            $this->id = $id;
        }
    }

    public function getID() {
        return $id;
    }

    public function isValid() {
        return time() < $expiry;
    }
}

class YourApp {
    public function newToken() {
        $token = new Token();
        $_SESSION['tokens'][$token->getID()] = $token;
        return $token
    }

    public function checkToken($token_id) {
        if( key_exists($token_id, $_SESSION['tokens']) ) {
            $cur = $_SESSION['tokens'][$token_id];
            unset($_SESSION['tokens'][$token_id]; // single use only!
            return $cur->isValid();
        } else {
            return false;
        }
    }

    public function flushOldTokens() {
        $_SESSION['tokens'] = array_filter(
            $_SESSION['tokens'],
            function($t){return $t->isValid();}
        );
    }
}