首页 > 解决方案 > Laravel API 在没有 CSRF 令牌的情况下无法工作(以及全球范围内的标头与我搞乱)

问题描述

我正在尝试在我的 Laravel 项目中设置一个 API,我想在我自己的项目中使用 Javascript。API 是无状态的,因此我的理解是 CRSF 令牌在请求 API 时变得无关紧要。我遇到以下两个问题:

  1. 当我尝试发送没有 X-CSRF-TOKEN 标头的请求时,我得到 401 Unauthorized

  2. 标头未正确应用于响应似乎存在问题

请求从子域 client.site.test 到子域 api.site.test 。我已通过将“InternalCORS”中间件应用于我的 API 路由来确保 CORS 已获得授权。

中间件 - 应用于所有 API 路由

class InternalCors {
    public function handle($request, Closure $next) {
        header('Access-Control-Allow-Origin:  https://client.site.test');
        header('Access-Control-Allow-Headers:  Content-Type, X-Auth-Token, X-CSRF-Token, X-Requested-With, Authorization, Origin');
        header('Access-Control-Allow-Methods:  GET, POST, PUT');
        header('Access-Control-Allow-Credentials: true');
        return $next($request);
    }
}

API 路由

Route::middleware('auth:api')->get('/testApi', function (Request $request) {
    return response()->json($request->user()->fullName(), 200);
})->name('testApi');

阿贾克斯查询

window.$.ajax({
    headers: {
        'Accept': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
    },
    xhrFields: {
       withCredentials: true
    },
    type: 'GET',
    url: 'https://api.site.test/testApi',
    success: function (response) {
        console.log(response);
    },
    error: function (xhr) {
        console.error(xhr.responseText);
    }
});

现在,即使中间件明确授权“凭据”,我也收到一个响应,说标题设置不是“”而不是“真”。所以我在顶部添加了一个 Nginx 指令:

add_header Access-Control-Allow-Credentials "true";

使用上面的设置,对请求的响应是“401 Unauthorized”。我已经加倍检查了 VerifyCsrfToken 中间件是否默认包含在web路由中,而不是api

我想说将 CRSF 令牌添加到 ajax 查询可以解决问题,但这并不是那么简单。有 3 个标头似乎会影响我得到的响应

[CSRF]:我是否在 Ajax 请求中发送 X-CSRF-TOKEN 标头

[MIDD HEADER]:我是否包含header('Access-Control-Allow-Credentials: true');在 API 路由的中间件中

[NGINX HEADER]:我是否add_header Access-Control-Allow-Credentials "true";在我的服务器配置中包含 API 路由

下面是对 Ajax 查询响应的回顾,具体取决于标头集:

[CSRF] [中间标题][NGINX 头文件]value of the 'Access-Control-Allow-Credentials' header in the response is ''

[CSRF] [中间头] [NGINX 头]:value of the 'Access-Control-Allow-Credentials' header in the response is 'true, true'

[CSRF][中间标题][NGINX 标头]:200 - John Smith

[CSRF][中间标题][NGINX 头文件]value of the 'Access-Control-Allow-Credentials' header in the response is ''

[CSRF][中间标头] [NGINX 标头]:401 Unauthorized

[CSRF] [中间标题][NGINX 标头]:value of the 'Access-Control-Allow-Credentials' header in the response is ''

我在这里不知所措...

标签: laravellaravel-passport

解决方案


您可以通过编辑在少数路由上禁用 CSRF。

App\Http\Middleware\VerifyCsrfToken 

并将您自己的路线名称添加到受保护的

$except = [] array.

你可以在这里查看更多


推荐阅读