简体   繁体   English

Laravel 5.5 Axios POST导致419错误

[英]Laravel 5.5 Axios POST results in 419 error

I am trying to make a POST-request to my Laravel API from Vue. 我正在尝试从Vue向我的Laravel API发出POST请求。 The X-CSRF-TOKEN header is set correctly (I see this in the POST-package sent to the server). X-CSRF-TOKEN标头设置正确(我在发送到服务器的POST包中看到了这一点)。

The route has the default web -middleware. 该路线具有默认的web中间件。

Request 请求

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Connection:keep-alive
Content-Length:2
Content-Type:application/json;charset=UTF-8
Host:api.xxx.local
Origin:http://manager.xxx.local
Referer:http://manager.xxx.local/location/planning/2
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
X-CSRF-TOKEN:EAf94SFJWBhlcwzxrq7nyygrnRSmZTavrnKYHv5C
X-Requested-With:XMLHttpRequest

Response 响应

Request URL:http://api.xxx.local/locationplanning/deleteentry/15
Request Method:POST
Status Code:419 unknown status
Remote Address:127.0.0.1:80
Referrer Policy:no-referrer-when-downgrade

Error Stack: 错误堆栈:

{
    "message": "",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\HttpException",
    "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
    "line": 203,
    "trace": [
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
            "line": 175,
            "function": "prepareException",
            "class": "Illuminate\\Foundation\\Exceptions\\Handler",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/app/Exceptions/Handler.php",
            "line": 47,
            "function": "render",
            "class": "Illuminate\\Foundation\\Exceptions\\Handler",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 83,
            "function": "render",
            "class": "App\\Exceptions\\Handler",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 55,
            "function": "handleException",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php",
            "line": 49,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\View\\Middleware\\ShareErrorsFromSession",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php",
            "line": 63,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\Session\\Middleware\\StartSession",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php",
            "line": 37,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php",
            "line": 59,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\Cookie\\Middleware\\EncryptCookies",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/app/Http/Middleware/ForgetDomainParameter.php",
            "line": 30,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "App\\Http\\Middleware\\forgetDomainParameter",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 102,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 647,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 622,
            "function": "runRouteWithinStack",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 588,
            "function": "runRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 577,
            "function": "dispatchToRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 176,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 30,
            "function": "Illuminate\\Foundation\\Http\\{closure}",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 30,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 30,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php",
            "line": 27,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php",
            "line": 46,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 149,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 102,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 151,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 116,
            "function": "sendRequestThroughRouter",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/Applications/XAMPP/xamppfiles/htdocs/kitchenradar/server/public/index.php",
            "line": 53,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        }
    ]
}

The problem here is that we're sending the request from one domain to another. 这里的问题是我们将请求从一个域发送到另一个域。 The web frontend domain is manager.xxx.local while the API domain is api.xxx.local . Web前端域是manager.xxx.local,而API域是api.xxx.local

This is important because cookies are constrained to the domain they originate from. 这很重要,因为cookie受限于它们源自的域。 For security, the browser will not send cookies to a different domain by default. 为安全起见,默认情况下, 浏览器不会将cookie发送到其他域 Laravel stores the CSRF token in the user's session for web requests and sends a session cookie to the browser to maintain this session. Laravel将CSRF令牌存储在用户会话中以获取Web请求, 并将会话cookie发送到浏览器以维护此会话。

Even though the bootstrap.js file , which ships with a default Laravel project, adds the CSRF token header for AJAX requests through axios, we still need a session so that Laravel can compare the token header to the value on the server. 即使bootstrap.js文件 (附带默认的Laravel项目)通过axios为AJAX请求添加了CSRF令牌头,我们仍然需要一个会话,以便Laravel可以将令牌头与服务器上的值进行比较。

We see the 419 HTTP status code—usually the result of a TokenMismatchException —because the API request is not associated with a user session (no session cookie), so no CSRF token state exists in the session . 我们看到419 HTTP状态代码 - 通常是TokenMismatchException的结果 - 因为API请求与用户会话没有关联(没有会话cookie),因此会话中不存在CSRF令牌状态 Because of this, Laravel considers the token invalid for the API request. 因此,Laravel认为该令牌对API请求无效。

We can solve this problem a couple of different ways. 我们可以通过几种不同的方式解决这个问题。 Modern browsers support Cross-Origin Resource Sharing (CORS) which, in part, allows us to share cookies between domains via AJAX. 现代浏览器支持跨源资源共享 (CORS),这部分允许我们通过AJAX在域之间共享cookie。 Our server needs to send the Access-Control-Allow-Credentials header: 我们的服务器需要发送Access-Control-Allow-Credentials标头:

Access-Control-Allow-Credentials: true

Read this article on MDN for more information. 有关更多信息,请阅读MDN上的这篇文章 The Laravel CORS package by Barry vd. Barry vd的Laravel CORS软件包。 Heuvel can help set this up if we don't want to manually configure our application or webserver. 如果我们不想手动配置我们的应用程序或Web服务器,Heuvel可以帮助设置它。

Then, we can configure AJAX requests to forward cookies to a different domain by setting the following property on the XMLHttpRequest : 然后,我们可以通过在XMLHttpRequest上设置以下属性来配置AJAX请求以将cookie转发到其他域:

xhr.withCredentials = true;

In axios, we can configure withCredentials per request : 在axios中,我们可以withCredentials每个请求配置withCredentials

axios.get(url, { withCredentials: true });

...or set it as the default: ...或将其设为默认值:

axios.defaults.withCredentials = true;

If we're using Vue Resource, we can set a similar configuration option: 如果我们使用Vue Resource,我们可以设置类似的配置选项:

Vue.http.options.credentials = true;

Even when we fix these issues, the current design relies on server-side sessions to maintain state for the CSRF token validation. 即使我们修复了这些问题,当前的设计依赖于服务器端会话来维护CSRF令牌验证的状态。 Conventional APIs are typically stateless (no server-side session tied to a user) and authenticate requests using some form of access token (OAuth, JWT, etc.). 传统的API通常是无状态的 (没有服务器端会话绑定到用户)并使用某种形式的访问令牌(OAuth,JWT等)对请求进行身份验证。 Note that the CSRF token is not one such token. 请注意,CSRF令牌不是这样的令牌。

For a more robust API framework, consider using Laravel Passport . 对于更强大的API框架,请考虑使用Laravel Passport We can add the CreateFreshApiToken middleware that automatically generates an encrypted JWT to pass the user ID and CSRF token state so that we can build a sessionless API. 我们可以添加CreateFreshApiToken中间件 ,该中间件自动生成加密的JWT以传递用户ID和CSRF令牌状态,以便我们可以构建无会话API。

If we don't want to build a full API, such as if our AJAX requests just supplement the views generated by the server, we may not want to complicate the application by using a separate domain for these requests. 如果我们不想构建完整的API,例如我们的AJAX请求只是补充服务器生成的视图,我们可能不希望通过为这些请求使用单独的域来使应用程序复杂化。

Notes: 笔记:

It works if I deactivate it but I need the Auth.... Auth::user() is null when I deactivate it. 它可以工作,如果我停用它但我需要Auth ....当我停用它时,Auth :: user()为null。

The user is null not because we deactivated CSRF, but because we don't have a session to begin with (the session cookie wasn't sent to the API domain). 用户为null 不是因为我们停用了CSRF,而是因为我们没有开始的会话(会话cookie未发送到API域)。

If I change the method to GET (in routes and axios) there is no error anymore 如果我将方法更改为GET(在路由和axios中),则不再存在错误

Laravel does not check the CSRF token for requests that semantically read data (GET, HEAD, and OPTIONS). Laravel不检查CSRF令牌以查找语义读取数据的请求(GET,HEAD和OPTIONS)。 It verifies the token only for requests that modify data (POST, PUT, DELETE, etc.). 它仅针对修改数据(POST,PUT,DELETE等)的请求验证令牌。

Side note : this is important to remember because an attacker can forge a GET request that modifies a user's data if we don't set up our routes appropriately. 旁注 :重要的是要记住,因为如果我们没有正确设置路由,攻击者可以伪造一个修改用户数据的GET请求。 Developers commonly make the mistake of using a link (often with .btn ) to make a simple request like deleting a record: 开发人员通常会错误地使用链接(通常使用.btn )来发出删除记录等简单请求:

<a href="/posts/delete/{id}">Delete Post</a>

A malicious site can place the same link on a page and the request will bypass CSRF protection when clicked because the browser sends a GET request for the link. 恶意站点可以在页面上放置相同的链接,并且请求将在单击时绕过CSRF保护,因为浏览器会发送链接的GET请求。

It's hard to see what's going on without checking many places in the project, so I'll list some possible causes, and hope that it'll point you in the correct direction 如果不检查项目中的许多地方,很难看到发生了什么,所以我会列出一些可能的原因,并希望它能指出你正确的方向

First probable cause, the 419 http code is trigerred by some condition in your source code. 第一个可能的原因,419 http代码在源代码中受到某些条件的影响。 This is higly unprobable given the callstack, but the error may be catched by some middleware and recreated (so wrong call stack). 考虑到callstack,这是非常不可能的,但是错误可能会被某些中间件捕获并重新创建(因此错误的调​​用堆栈)。

Another probable cause, the CSRF protection. 另一个可能的原因,CSRF保护。 Given that it works for GET and not for POST (see comments), it's highly probable that the CSRF protection is triggered and refuse the request. 鉴于它适用于GET而不适用于POST(请参阅注释),很可能会触发CSRF保护并拒绝请求。 To correct that, simply disable the CSRF middleware by using the api (instead of web ) middleware OR adding the route into VerifyCsrfToken class. 要纠正这个问题,只需使用api (而不是web )中间件或将路由添加到VerifyCsrfToken类中来禁用CSRF中间件。 See How to disable some routes for CSRF validation 请参见如何禁用CSRF验证的某些路由

CSRF protection isn't needed for API routes, these are needed only for POST forms on "standard" webpages. API路由不需要CSRF保护,只有“标准”网页上的POST表单才需要这些保护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM