使用Joomla自定义组件的令牌无效

时间:2013-01-11 19:43:52

标签: joomla joomla2.5

我正在构建一个自定义的Joomla组件,我在我的模板(default.php)文件中添加了这个(它正在使用HTTP POST):

echo JHTML::_( 'form.token' ); //add hidden token field to prevent CSRF vulnerability

然后我用控制器检查控制器中的令牌:

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

但无论我做什么,我都会得到一个无效的令牌。我已经验证了当我在html页面上查看源时,在我的表单中创建了带有令牌的隐藏类型。我还验证了,在控制器中,令牌的值是相同的:

print_r(JUtility::getToken());

因此,如果令牌是相同的值,为什么它会以无效令牌消息退出?

编辑:我没有提到一个关键部分。我的表单使用jquery ajax在我的view.html.php中添加的单独的js文件中处理。这就是ajax POST的样子:

jQuery.ajax({
    type: 'POST',
    url: 'index.php?option=com_recordings&task=deletevideos&format=raw',
    data: {checkedarray:checked},
    success: function(data){
               //delete row
    }
});

控制器处理:

function deletevideos()
{

    $video_list = JRequest::getVar('checkedarray', 0, 'post', 'array');
    //print_r(JUtility::getToken());
    JRequest::checkToken() or jexit( 'Invalid Token' );     

    $model = &$this->getModel();
    return $model->setDeleteVideos($video_list);
}

然后转到进行数据库更新的模型。我看到了可能相关的旧post。我不清楚如何/在哪里生成令牌以及我在何处/如何验证该令牌。该帖子似乎非常复杂,因为它检查用户,我认为在我的情况下不需要。或者我误解了?

编辑#2

好的,所以令牌丢失了,我需要将它传递给我的js文件。所以我想我可以将它添加到我的view.html.php:

    $addtoken = JUtility::getToken();
    $addtokenjs = 'jQuery(function() {
                    var token="'.$addtoken.'";
                    });';
    $doc->addScriptDeclaration( $addtokenjs );
    $doc->addScript(JURI::base()."components/com_recordings/js/recordings.js");

我必须把它放在文档就绪函数中,因为显然addScriptDeclaration没有把任何东西放在我的recordings.js文件之前。然后将令牌传递到ajax电话:

jQuery.ajax({
    type: 'POST',
    url: 'index.php?option=com_recordings&task=deletevideos&format=raw'+token+'=1',
    data: {checkedarray:checked},
    success: function(data){
               //delete row
    }
});

显然我没有这样做,因为我收到此错误:ReferenceError: token is not defined

5 个答案:

答案 0 :(得分:4)

您似乎没有在ajax请求中传递令牌值。这就是您收到此错误的原因。

你可以 - 1)像这样将URL添加到URL

url: 'index.php?option=com_recordings&task=deletevideos&format=raw&'. JUtility::getToken() .'=1'

2)或使用Serialize发送整个表单。

编辑2: -  您可以像这样创建一个名为getToken的函数 -

 $addtokenjs = 'function getToken() {
                    var token="'.$addtoken.'";
                    return token;
                    };';

在网址中,您可以拨打token

而不是拨打getToken()
url: 'index.php?option=com_recordings&task=deletevideos&format=raw'+getToken()+'=1'

希望这会奏效。

答案 1 :(得分:2)

尝试使用

JSession::checkToken() or die( JText::_( 'Invalid Token' ) );

而不是JRequest。我更喜欢JSession的原因是因为它保证了Joomla 2.5 / 3.0兼容性,而不必考虑JRequest被弃用。在Joomla 2.5中,该函数使用JRequest,而在3.0中使用JInput。


修改

对于AJAX,您实际上需要使用POST传递数据。您的数据目前只是checkedarray:checked,即已检查的数据,而不是AJAX请求中的令牌。如果您希望使用POST方法,则需要使用serialize传递数据。但请注意,序列化无论如何都会将数据放在URL中。然后,您可以使用

处理此令牌
// Check for request forgeries using one of either JRequest of JSession
JRequest::checkToken( 'get' ) or jexit( 'Invalid Token' );
//Alternative
JSession::checkToken( 'get' ) or jexit( 'Invalid Token' );

为了完整,您提供的链接使用GET方法。因为你可以在他的AJAX函数的第三行看到他传递的用户名(在他的情况下)和URL中的标记

function check_username(username, token) {
  var url = 'index.php?option=com_user&task=check_user';
  data = 'username=' + username + '&' + token;     //TOKEN INSERTED INTO URL HERE
 $.ajax({
  type: "GET",
  url: url,
  data: data,
  success: function(xml) {
    var result = $(xml).find('response').text();
    if (result == 'found') {
       alert( 'Please select a different username, ' + username + ' already exists' );
   }
   }
  }); // ajax
}

然后在此之后使用

进行处理是微不足道的
// Check for request forgeries using one of either JRequest of JSession
JRequest::checkToken( 'get' ) or jexit( 'Invalid Token' );
//Alternative
JSession::checkToken( 'get' ) or jexit( 'Invalid Token' );

无论哪种方式,它可能会涉及到你的模型的一些调整 - 当你传递超过1个变量 - 虽然它应该不难做到。希望这有帮助!

答案 2 :(得分:1)

如果表单数据提交为$_GET

JRequest::checkToken('get') or jexit( 'Invalid Token' );;

如果表单数据提交为$_POST

JRequest::checkToken('post') or jexit( 'Invalid Token' );;

否则,您可以使用下面的首选

JRequest::checkToken('request') or jexit( 'Invalid Token' );

Read more

答案 3 :(得分:1)

初始代码的明显问题是您没有将令牌传递给控制器​​。

data: {checkedarray:checked}可能只包含您要删除的ID数组。

Irfan版本是最容易实现的,它应该可以工作。我成功地使它成功了。

这是gist with the working code(请注意,这不是生产就绪代码,只是为了测试令牌问题)。但我测试了它,它对我有用。

答案 4 :(得分:1)

以防将来使用:在Joomla上! 3.x JUtility::getToken()已替换为JSession::getFormToken()

见这里:http://api.joomla.org/cms-3/classes/JSession.html#method_getFormToken