UserFrosting表单 - CSRF令牌无效或缺失

时间:2016-11-21 12:06:59

标签: php userfrosting fortress

我正在尝试在 UserFrosting 中提交一个简单的表单,并且作为测试仅显示成功消息,而不进行数据修改。我遵循了Lesson 2的指导,但我遇到了 CSRF 问题:

UserFrosting会返回以下错误:

  

CSRF令牌无效或缺失。

我错过了什么?到目前为止, UserFrosting 非常容易理解:(

表格:

<form class="form-horizontal" role="form" name="requestDescription" action="{{site.uri.public}}/soap/requests/desc/edit/{{ keyname }}" method="post">
    <div class="form-group">
        <label for="input_group" class="col-md-2 control-label">Name</label>
        <div class="col-md-10">
            <input type="text" id="input_name" class="form-control" name="lgname" placeholder="{{ name }}">
        </div>
    </div>
    <div class="form-group text-center">
        <button type="submit" class="btn btn-success text-center">Update</button>
    </div>
</form>

在twig文件的底部添加了脚本部分:

<script>
    $(document).ready(function() {
        // Load the validator rules for this form
        var validators = {{validators | raw}};
        ufFormSubmit(
                $("form[name='requestDescription']"),
                validators,
                $("#userfrosting-alerts"),
                function(data, statusText, jqXHR) {
                    // Reload the page on success
                    window.location.reload(true);
                }
        );
    });
</script>

以下是我在控制器中的两个功能:

public function soapRequestDescriptionEditPage($keyname){
    if (!$this->_app->user->checkAccess('uri_soap_requests')){
        $this->_app->notFound();
    }
    $requestDetails = $this->soapRequestReadMeta($keyname);

    $schema = new \Fortress\RequestSchema($this->_app->config('schema.path') . "/forms/soap-request-description-edit.json");
    $this->_app->jsValidator->setSchema($schema);

    $this->_app->render('soap/soap-request-description-edit.twig', [
        "name" => $requestDetails['name'],
        "description" => $requestDetails['description'],
        "keyname" => $keyname,
        "validators" => $this->_app->jsValidator->rules()
    ]);
}

public function test(){
    if (!$this->_app->user->checkAccess('uri_soap_requests')) {
        $this->_app->notFound();
    }
    $post = $this->_app->request->post();
    $ms = $this->_app->alerts;
    $requestSchema = new \Fortress\RequestSchema($this->_app->config('schema.path') . "/forms/soap-request-description-edit.json");
    $rf = new \Fortress\HTTPRequestFortress($ms, $requestSchema, $post);
    $ms->addMessageTranslated("success", "Everyone's title has been updated!", $post);
    $rf->sanitize();
    if (!$rf->validate()) {
        $this->_app->halt(400);
    }
    $data = $rf->data();
}   

index.php 文件中的条目:

$app->post('/soap/requests/desc/edit/:request_id/?', function () use ($app) {
    $controller = new UF\SoapController($app);
    return $controller->test();
});
$app->get('/soap/requests/desc/edit/:request_id/?', function ($request_id) use ($app) {
    $controller = new UF\SoapController($app);
    return $controller->soapRequestDescriptionEditPage($request_id);
});

最后,架构:

{
  "lgname" : {
    "validators" : {
      "length" : {
        "min" : 1,
        "max" : 150,
        "message" : "The new title must be between 1 and 150 characters long."
      }
    },
    "sanitizers" : {
      "raw" : ""
    }
  }
}

2 个答案:

答案 0 :(得分:1)

从UserFrosting 4开始,您应该将隐藏的CSRF输入字段显式添加到表单中。有一个部分模板forms/csrf.html.twig包含这些字段,您可以使用Twig的include标记插入这些字段:

<form class="form-horizontal" role="form" name="requestDescription" action="{{site.uri.public}}/soap/requests/desc/edit/{{ keyname }}" method="post">
    {% include "forms/csrf.html.twig" %}
    <div class="form-group">
        <label for="input_group" class="col-md-2 control-label">Name</label>
        <div class="col-md-10">
            <input type="text" id="input_name" class="form-control" name="lgname" placeholder="{{ name }}">
        </div>
    </div>
    <div class="form-group text-center">
        <button type="submit" class="btn btn-success text-center">Update</button>
    </div>
</form>

对于没有表单的请求(例如,如果它是纯粹用Javascript构建的),您可以从全局site.csrf变量中获取CSRF令牌名称和值:

var userName = 'luke';
var fieldName = 'lgname';

var data = {
    'value': fieldValue
};

data[site.csrf.keys.name] = site.csrf.name;
data[site.csrf.keys.value] = site.csrf.value;

var url = site.uri.public + '/api/users/u/' + userName + '/' + fieldName;

return $.ajax({
    type: "PUT",
    url: url,
    data: data
}).done(function (response) {
    window.location.reload();
});

答案 1 :(得分:0)

原来我的代码很好。页面上存在不相关的javascript错误,影响UserFrosting表单处理。修复这些错误允许UserFrosting处理表单。

注意自己...养成查看控制台的javascript错误的习惯:)