【问题标题】:Session tokens in PHP being cached by JoomlaJoomla 缓存 PHP 中的会话令牌
【发布时间】:2013-06-05 18:31:59
【问题描述】:

我正在将 Joomla 用于一个项目,并且发生了一些 Ajax 请求来填充数据。我在 PHP 视图中生成一个 Joomla 会话令牌,并将其附加到 Ajax 请求端点的 URL 上,该端点也是一个 PHP 页面,并在返回数据之前验证令牌。

类似这样的:

// view.html.php
$script = "var ajaxurl = 'index.php?task=ajaxFunction&".JFactory::getSession()->getFormToken()."=1';";
$document->addScriptDeclaration($script);

// ajax.js
var request = new Request.JSON({
    url: ajaxurl,
    onException: function(headerName, value) {
        // etc.
    }
});

// controller
public function ajaxfunction()
{
    JRequest::checkToken('get') or die( 'Invalid Token!' );
    // do other stuff
}

在启用缓存之前,这一切正常。

问题在于view.html.php 文件,当 Joomla 使用其内部缓存时,会使用已设置的令牌进行缓存——因此,每当浏览器请求页面时,它都会将缓存的令牌连同它一起拉出,这意味着控制器将返回一个无效的 Token 错误。

我知道在早期的 Joomla 构建中,缓存完全不起作用。有没有办法在 Joomla 2.5+ 中完成这项工作,而不仅仅是禁用 Joomla 缓存?我找不到从缓存中排除单个视图的任何方法。

【问题讨论】:

    标签: php session caching joomla


    【解决方案1】:

    也许您可能希望将请求作为 POST 而不是 GET 发送,它不会使用 Joomla 缓存。

    ajax.js

    var userToken = document.getElementsByTagName("input")[0].name;
    
    var request   = new Request.JSON({
        url: 'index.php?task=ajaxFunction&'+ userToken +'=1',
        onException: function(headerName, value) {
            // etc.
        }
        onComplete: function(res) {
            // etc.
        }
    
    }).post({});
    

    控制器

    JRequest::checkToken('get') or die( 'Invalid Token!' );
    

    将其粘贴在模板文件的顶部(在所有其他输入标记之前),它将创建一个包含标记的隐藏输入字段,最终将在渲染时替换为非缓存的输入字段

    tmpl/default.php

    <?= JHtml::_('form.token'); ?>
    

    【讨论】:

    • 好吧,问题是在您的view.html.php 中,对getFormToken 的调用是被缓存的部分——该令牌是“硬编码”的,并且无论是否发送,它总是错误的通过 POST 或 GET。
    • 嗨。你是对的 julio 缓存是非常脆弱的东西。我已经更新了我的答案。
    • getElementByTagName 可能不是最好的选择,但应该给你一个线索。其他选项是将 JHtml 令牌放在带有 ID 的 div 中,首先通过 ID 在 JavaScript 中获取 div,然后使用我们的会话令牌属性获取其子输入。无论哪种方式,joomla 总是在从缓存打印之前替换隐藏的令牌输入
    • WooDzu 的好东西——感谢您的坚持。你已经赢得了赏金,这种策略效果很好。在 Joomla 中似乎仍然应该有一种更“核心”的方式来处理这个问题,类似于 nietonfir 的建议——但这会让我到达那里。
    • 参见 JCache 类,joomla 搜索整个输入字段并在打印缓冲区之前用 preg_repleace 更新其中的令牌。这就是为什么这些令牌始终是最新的
    【解决方案2】:

    有时我使用 Ajax 和 Joomla 并真的没有这个问题。好吧,也许你的工作方式,也许最好尝试不同的缓存方式,所以如果你真的没有希望,只需从 Joomla 分叉 System - Cache,然后在你的分叉上进行不缓存你不想要的东西。如果在您的项目中可以处理您的缓存方式,您也可以不使用 Joomla Cache 并将其与 Varnish 或类似内容一起使用。

    我认为它应该比你现在做的更好:Joomla 有一个小组来包含一种使用 AJAX 的“标准”方式,你可以在这里看到一个概念证明:

    在这里讨论

    另外,关于使用 Ajax 的另一种方法在这里

    【讨论】:

    • 嗨——不幸的是,破解核心系统缓存不是一种选择。
    • Fork(创建副本、更改和安装)不是 Joomla 核心中的 hack。
    • 你误解了我的意思。期望用户修改核心 Joomla 文件不是一种选择。
    • 如果您需要为特定视图或任务禁用缓存,除了创建自己的缓存插件之外别无他法。所以路易斯就在这里
    【解决方案3】:

    通过查看JSession::getFormToken()method signature,您应该能够通过调用getFormToken(true) 来强制使用新令牌。

    这应该可以避免您遇到的任何缓存问题。

    【讨论】:

    • 而且它甚至不会让您在关闭缓存的情况下提交请求
    【解决方案4】:

    我在 joomla 中使用非常相似的设置执行此操作的方式是使用 JavaScript 注入值。页面在没有令牌的情况下被缓存,JavaScript 在发出请求之前添加它

    您可以使用 cookie 或其他 ajax 请求传递值。 Cookies 最适合我

    【讨论】:

    • 这听起来像我正在寻找的东西。能举个例子吗?
    • 我目前正在使用平板电脑,因此无法很好地输入代码。明天就可以了
    猜你喜欢
    • 1970-01-01
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 2012-06-12
    • 2018-08-02
    • 2014-08-02
    • 2019-02-04
    相关资源
    最近更新 更多