【问题标题】:Userfrosting: Get working, but not PostUserfrosting:开始工作,但不发布
【发布时间】:2016-07-27 01:51:57
【问题描述】:

当使用“获取”请求调用 url 时,我能够得到很好的响应。

但是,当我通过“发布”请求调用相同的网址时,我收到了“错误请求”。关于为什么会发生这种情况的任何建议/想法?

index.php 文件中的代码:

//GET Request: This works fine!

$app->get('/api/ss20/registration/?', function () use ($app) {
            echo "hello-get";
});


//POST Request: This gives a bad request error!

$app->post('/api/ss20/registration/?', function () use ($app) {
            echo "hello-post";
});

我用来发出 get 请求的简单表单:

<form action="api/ss20/registration/" method="get">
  First name: <input type="text" name="fname"><br>
  Last name: <input type="text" name="lname"><br>
  <input type="submit" value="Submit">
</form>

我用来发出帖子请求的简单表单:

<form action="api/ss20/registration/" method="post">
  First name: <input type="text" name="fname"><br>
  Last name: <input type="text" name="lname"><br>
  <input type="submit" value="Submit">
</form>

尝试使用 postman / Arc 来模拟请求。并且获取请求工作正常,但不是帖子。

【问题讨论】:

    标签: slim userfrosting


    【解决方案1】:

    由于缺少CSRF 令牌,您很可能会收到400 错误请求错误。

    在 0.3.1 版本中,UserFrosting 将 CSRF 令牌存储在页面的 &lt;head&gt; 标记内的特殊 &lt;meta&gt; 标记中。例如,如果我查看 account/settings 页面的源代码,我会看到:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="Update your account settings, including email, display name, and password.">
        <meta name="author" content="Alex Weissman">
        <meta name="csrf_token" content="583caa307d5c1027a8983251f13a3fe994050001d871e329b16599a29858652891a10c48535c6e4be0580c87503f210072ca83c0a45d49c0d0941b5b2536aa15"> 
    
        <title>UserFrosting | Account Settings</title>
        ...
    

    因此,您需要以某种方式将 csrf_token 的值添加到您的 POST 提交中。通常,如果您使用 Javascript 使用 ufFormSubmit 函数提交表单,UserFrosting 会自动执行此操作。

    您会注意到以下几行:

    // Append page CSRF token
    var csrf_token = $("meta[name=csrf_token]").attr("content");
    serializedData += "&csrf_token=" + encodeURIComponent(csrf_token); 
    

    这些只是从&lt;meta&gt; 标记中获取csrf_token 值并将其附加到表单的数据中。请注意,要调用此函数,您需要确保页面上没有任何 Javascript 错误。否则,大多数浏览器会默认默认为“传统”表单提交,并且 CSRF 令牌不会附加到您的表单中。

    如果您确实想以“传统”方式提交表单,您可以将 CSRF 令牌作为隐藏字段直接插入到 Twig 模板中。只需添加

    &lt;input type="hidden" name="{{csrf_key}}" value="{{csrf_token}}"&gt;

    到您的表格。更多关于UserFrosting and CSRF tokens here

    【讨论】:

    • API 调用正在由另一个服务进行。可以在没有 CSRF 令牌的情况下进行调用吗?
    • 在这种情况下,您必须将处理来自该服务的请求的路由列入白名单。要在 UF 0.3.1 中执行此操作,您必须修改 CsrfGuard 类。
    • 谢谢@alexw。做到了!
    【解决方案2】:

    我需要修改 middleware/CsrfGuard.php 以将 API url 列入白名单

    添加了以下 if 语句。它检查对 /api/ss20/registration 的 POST 请求是否被忽略。

    if (!(in_array($this->app->request()->getMethod(), array('POST')) && $uri->getPath() == "/api/ss20/registration"))
            {
                if (in_array($this->app->request()->getMethod(), array('POST', 'PUT', 'DELETE')))  {
    
                     //error_log("\n".date(DATE_RSS)." Inside CSRF Validation",3, "/tmp/php-error.log");
    
                    $userToken = $this->app->request()->post($this->key);
                    if ($token !== $userToken) {
                        //error_log("\n".date(DATE_RSS)." About to send halt-400",3, "/tmp/php-error.log");
                        $this->app->alerts->addMessage('danger', 'Invalid or missing CSRF token.');
                        $this->app->halt(400);
                    }
                }
    }
    

    谢谢@alexw

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多