2

我正在构建一个自定义 Joomla 组件,并将其添加到我的模板 (default.php) 文件中的表单中(它使用的是 HTTP POST):

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

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

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

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

print_r(JUtility::getToken());

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

编辑:有一个我没有提到的关键部分。我的表单是在一个单独的 js 文件中使用 jquery ajax 处理的,该文件添加到我的 view.html.php 中。这是 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);
}

This then goes to the model that does the DB update. I saw this old post that might be relevant. It is not clear to me how/where I generate the token and where/how I validate that token. The post seems quite involved as it checks against users as well which I don't think is needed in my case. Or maybe I misunderstand?

EDIT #2

Okay so the token is missing and I need to pass it into my js file. So I thought I could add this to my 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");

I have to put this in the document ready function because apparently addScriptDeclaration does not put anything ahead of my recordings.js file. Then pass the token into the ajax call:

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

Apparently I'm not doing this right as I get this error: ReferenceError: token is not defined.

4

5 回答 5

4

It does not seem that you are passing token value in the ajax request.And that's why you are getting this error.

You can - 1) append token to the url like this

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

2) Or send the whole form using Serialize.

EDIT 2:- You can create a function called getToken like this-

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

And in url instead of calling token you can call getToken()

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

Hope this will work.

于 2013-01-21T07:01:09.160 回答
2

Try using

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

rather than JRequest. The reason I like JSession more is because it guarentees Joomla 2.5/3.0 compatibility without having to think about JRequest being deprecated. In Joomla 2.5 the function uses JRequest and in 3.0 uses JInput.


EDIT

For the AJAX ou actually need to pass the data across with the POST. Your data is currently just going to be the checkedarray:checked i.e. the checked data and NOT the token in the AJAX request. You'll need to pass the data across with serialize if you wish to use the POST method. However note that serialize will place the data in the URL anyhow. You can then process this token with

// 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' );

Just for completelness the link you have given uses the GET method. In that he's passed across the username (in his case) and the token in the URL as you can see on the third line of his AJAX function

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
}

and then after this is it is trivial to process just using

// 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' );

Either way its probably going to involve some tweaking to your model - as your passing across more than 1 variable - although it shouldn't be hard to do. Hope this helps!

于 2013-01-21T01:34:51.917 回答
1

If the form data is submitted as $_GET

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

If the form data is submitted as $_POST

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

Else you can use below which is preferred

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

Read more

于 2013-01-19T11:22:13.447 回答
1

The obvious problem with your initial code is that you are not passing the token to the controller.

data: {checkedarray:checked} probably contains just an array of IDs you want to delete.

Irfan version is the easiest to implement and it should work. I've managed to make it work.

Here is a gist with the working code (please note that this is not production ready code, it's just to test the token problem). But I've tested it and it works for me.

于 2013-01-21T19:34:27.867 回答
1

Just in case of future use: On Joomla! 3.x JUtility::getToken() has been replaced with JSession::getFormToken().

See here: http://api.joomla.org/cms-3/classes/JSession.html#method_getFormToken

于 2014-02-04T23:59:46.013 回答