使用 laravel-cors 和 axios 进行 POST 的 Laravel “CSRF 令牌不匹配”
Posted
技术标签:
【中文标题】使用 laravel-cors 和 axios 进行 POST 的 Laravel “CSRF 令牌不匹配”【英文标题】:Laravel “CSRF token mismatch” for POST with laravel-cors and axios 【发布时间】:2019-11-11 11:04:15 【问题描述】:我有一个 domain_A 正在运行 Laravel 5.8 引擎以返回 web 路由 上的 API。它必须检查来源才能只服务几个域,包括 domain_B。
Barryvdh/laravel-cors 我通过 composer 安装了barryvdh/laravel-cors 并对其进行了全局配置,更新了 Kernel.php。这也应该适用于网络路由。
kernel.php
protected $middleware = [
...
\Barryvdh\Cors\HandleCors::class,
];
然后我配置 Laravel Cors 使用标准配置作为测试以允许任何域。
/config/cors.php
return [
'supportsCredentials' => false,
'allowedOrigins' => ['http:www.domain_b.com','https:www.domain_b.com','http:domain_b.com'],
'allowedHeaders' => ['Access-Control-Allow-Origin', 'X-CSRF-TOKEN', 'Content-Type', 'X-Requested-With'],
'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,
];
axios 配置是:
(domain_a)/Repository.js
import axios from 'axios/index';
const baseDomain = "https://domain_a";
const baseURL = `$baseDomain`;
let withCredentials = false;
const token = document.head.querySelector('meta[name="csrf-token"]');
const headers =
'X-CSRF-TOKEN': token.content,
'Access-Control-Allow-Origin': '*',
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json',
;
export default axios.create(
baseURL,
withCredentials: withCredentials,
headers: headers
);
GET 请求也被过滤,PUT 请求返回 419 错误,为什么?我已经设置了 'allowedMethods' => ['*'] 所以它应该可以工作......我错过了什么?
[编辑]
在调试时,我现在收到此错误...
消息:“CSRF 令牌不匹配。”
为什么 POST 没有得到头部 Token?
我也尝试像这样传递 POST 令牌:
const token = document.head.querySelector('meta[name="csrf-token"]');
const options =
headers:
'Authorization' : 'bearer '+token.content,
;
const body = ;
return Repository.post(`$resource/$$playerId/$$cozzaloID`, body, options)
预检标头响应
Access-Control-Allow-Headers: authorization, content-type, x-requested-with, x-csrf-token
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: http://www.******.**
Cache-Control: no-cache, private
Connection: Keep-Alive
Content-Length: 0
Content-Type: text/html; charset=UTF-8
Date: Mon, 01 Jul 2019 05:14:22 GMT
Keep-Alive: timeout=5, max=98
Server: Apache
X-Powered-By: PHP/7.1.30, PleskLin
标头响应:
Access-Control-Allow-Origin: http://www.xxxxxxx.xx
Cache-Control: no-cache, private
Connection: Keep-Alive
Content-Type: application/json
Date: Mon, 01 Jul 2019 05:14:22 GMT
Keep-Alive: timeout=5, max=97
Server: Apache
Transfer-Encoding: chunked
Vary: Origin,Authorization
X-Powered-By: PHP/7.1.30, PleskLin
标头请求:
Provisional headers are shown
Accept: application/json, text/plain, */*
Authorization: Bearer jW6pFcVlkKyApCxtZIlfaHDPMSFWCWcbnPPTQ7EJ
Content-Type: application/json
Origin: http://www.xxxxxxx.xx
Referer: http://www.xxxxxx.xx/players/739
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100
Safari/537.36
X-CSRF-TOKEN: jW6pFcVlkKyApCxtZIlfaHDPMSFWCWcbnPPTQ7EJ
X-Requested-With: XMLHttpRequest
token注意事项:应该没问题,因为它与在同一任务中完成的另一个 GET 请求相同。
【问题讨论】:
您不需要将 Access-Control-Allow-Origin 放入 allowedHeaders 值中。 坦克。在客户端和服务器端都删除了:GET 它正在工作,而 POST 继续不能为传递的错误令牌工作 你试过'Bearer '+token.content
吗?也就是说,大写,而不是bearer
。不知道是不是区分大小写……
它应该可以使用和不使用任何大写字母。但对我来说不是:(
您是否尝试过调试以确保您的document.head.querySelector('meta[name="csrf-token"]')
确实达到了您的预期?那token.content
是?
【参考方案1】:
api路由请使用routes/api.php, 不要将 routes/web.php 用于 api。
如果您想使用子域,请在以下文件中进行必要的更改:
app/Providers/RouteServiceProvider.php
原文:
protected function mapApiRoutes()
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
更新:
protected function mapApiRoutes()
Route::domain('api.' . env('APP_URL'))
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
【讨论】:
感谢米兰的来信!我更喜欢使用专用子域 (api.domain.com) 而不是 www.domain.com/api。出于这个原因,我正在使用网络路由。你认为这不正确吗?为什么? 哇!感谢@Milan,我认为解决了我的问题!!!我必须将 ENV var APP_URO 从 APP_URL=api.domain.org 更改为 APP_URL=domain.org 可以吗?还是会产生不好的影响? 在您的情况下,您必须将 APP_URL 设置为主域。这是正确的方法,不要担心。 我在发送恢复密码链接时遇到问题,因此我收到了具有双域的链接:api.domain.org/domain.org/password/reset/xxxx。你能帮我修一下吗?谢谢!! ***.com/questions/57073662/…【参考方案2】:地址
供应商/fruitcake/laravel-cors/src/HandleCors.php
对此发表评论
// Check if we're dealing with CORS and if we should handle it
if (! $this->shouldRun($request))
return $next($request);
【讨论】:
以上是关于使用 laravel-cors 和 axios 进行 POST 的 Laravel “CSRF 令牌不匹配”的主要内容,如果未能解决你的问题,请参考以下文章
Laravel/React:barryvdh/laravel-cors 处理预检 HTTP OPTIONS 请求
barryvdh/laravel-cors 不适用于我的路线
barryvdh/laravel-cors 配置在 Laravel 5.6 中不起作用;忽略'allowedMethods'