【问题标题】:Why does the Laravel API return a 419 status code on POST and PUT methods?为什么 Laravel API 在 POST 和 PUT 方法上返回 419 状态码?
【发布时间】:2018-02-26 05:43:48
【问题描述】:

我正在尝试使用 Laravel 创建一个 RESTful API。我使用 php artisan make:controller RestController 创建了我的控制器,这是我的控制器代码:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class RestController extends Controller
{
    private $arr = array(
            array("name"=>"jon", "family"=>"doe"),
            array("name"=>"jhon", "family" => "doue")
        );
    public function index(){
        return json_encode($this->arr);
    }

    public function store(Request $request){
        return "oops!!";
    }

    public function update (Request $request, $id){
        return "test";
    }

}

我已经在我的 routes/web.php 文件中添加了这行代码来创建这个路由:

Route::resource('person', 'RestController');

当我尝试在 GET /person 上测试此 api 时,它工作正常,但在 POST 和 PUT 上,我从 Laravel 获得 419 状态代码。

【问题讨论】:

  • 可能是验证失败,或者如果它的 psot 请求则没有添加令牌
  • 我的控制器上没有验证。我必须添加的令牌是什么
  • 你为 POST 请求定义路由了吗?
  • 不...我使用 route::resource

标签: php rest laravel-5


【解决方案1】:

如果您正在开发 REST API,最好不要添加令牌。如果您使用的是 5.4 或 5.5,则可以使用 api.php 而不是 web.php。在api.php 中,您不需要对发布请求进行令牌验证。

如果您使用web.php,则可以排除您不想使用 CSRF 令牌验证的路由。

这里是官方文档:

从 CSRF 保护中排除 URI

有时您可能希望从 CSRF 保护中排除一组 URI。例如,如果您正在使用 Stripe 处理付款并使用他们的 webhook 系统,则需要从 CSRF 保护中排除您的 Stripe webhook 处理程序路由,因为 Stripe 不会知道要向您的路由发送什么 CSRF 令牌。

通常,您应该将这些类型的路由放在RouteServiceProvider 应用于routes/web.php 文件中的所有路由的web 中间件组之外。但是,您也可以通过将路由的 URI 添加到 VerifyCsrfToken 中间件的 $except 属性来排除路由:

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ];
}

供参考https://laravel.com/docs/5.5/csrf

【讨论】:

  • 如果我想添加令牌我必须使用哪个令牌
  • 不可能在 api 中添加 laravel 令牌。因为 api 是从第三方应用程序(如 android 或 ios 或任何其他网络应用程序)消耗的
  • 我添加了 Route::resource('person', 'RestController');到我的 api.php 但我仍然收到 419 状态代码
  • 你这是因为令牌不存在。你可以更改为受保护的 $except = [ '/*', ];在 App\Http\Middleware\VerifyCsrfToken
【解决方案2】:

据我所知,有两种方法可以解决这个问题

方法一:添加CsrF Token

方法 2:将 URI 排除在 CSRF 保护之外

如何使用

方法 1:在 POST 请求中再添加一个变量

_token: "{{ csrf_token() }}"

Ajax 示例

req = $.ajax({
    type: "POST",
    url: "/search",
    data: {
        "key": "value",
        _token: "{{ csrf_token() }}",
    },
    dataType: "text",
    success: function(msg) {
        // ...
    }
});

如果您使用表单的示例

<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}">

方法二:在以下位置有一个名为VerifyCsrfToken的文件

yourProjectDirectory/app/Http/Middleware

通过以下方法添加您的网址

 protected $except = [
     'url1/',
     'url2/',
 ];

何时使用

  • 如果您是 API 的所有者(完全控制),请使用方法 1,因为 CSRF Token 为您的应用程序增加了安全性。

  • 如果您无法添加 CSRF 令牌,例如使用任何第三方 API、webhook 等,请选择方法 2。

【讨论】:

    【解决方案3】:

    我通过更改我的服务器 缓存 设置解决了这个问题。 您可以禁用所有缓存系统(Nginx、Cloudflare、...)来检查它,然后 通过应用QueryString + Cookie 将其打开,以防止缓存包含旧csrf token 的页面。

    【讨论】:

      【解决方案4】:

      这可以通过排除你想要的特定路由的csrf保护来解决。

      在您的中间件文件夹中,编辑名为 VerifyCsrfToken.php 的文件

      protected $except = [
          'http://127.0.0.1:8000/person/'
      ];
      

      【讨论】:

        猜你喜欢
        • 2021-06-21
        • 2022-01-03
        • 2019-05-18
        • 1970-01-01
        • 2017-07-29
        • 1970-01-01
        • 2018-08-24
        • 2021-09-20
        • 1970-01-01
        相关资源
        最近更新 更多