php - api 端点未在 Sanctum 上进行 CSRF token 验证 - CSRF token 不匹配

标签 php laravel csrf laravel-sanctum

我目前正在学习 Laravel(这不是特别顺利)并且我已经配置了几个路由来使用 sanctum 测试身份验证。
我正在构建一个仅限 API 的 laravel 服务,并计划 ReactJS 项目将使用该 API。
我目前虽然没有使用 ReactJS 并使用 Insomnia REST 客户端来测试 API。
我有一条用于注册新用户、登录的路由,然后是另一条仅返回经过身份验证的用户以证明身份验证机制正常工作的路由。
我对 CSRF 了解不多,但我的理解是我请求一个新的 CSRF token ,然后对于 API 的每个请求都使用此 CSRF token ,例如,当我登录然后从相应的路由获取经过身份验证的用户时, CSRF token cookie 也被发送,因此如果发送不同的 CSRF token ,我应该收到 token 不匹配错误。
我正在使用 Insomnia 进行测试,方法是向/sanctum/csrf-cookie 发送请求,该请求会返回 204 并且 Insomnia 设置了 3 个 cookie,其中一个是 XSRF-TOKEN,我理解它是 CSRF token 的加密形式。
然后我成功登录,然后当我调用我的路由以获取经过身份验证的用户时,我修改或删除 XSRF-TOKEN cookie 并发送请求,然后我希望收到有关 token 不匹配的错误,但这不会似乎是这样,我得到了有效的回复。
下面是我的 api.php(我将各种路由分组到单独的 PHP 文件中,以便在我实际构建 API 时保持组织有序)

Route::prefix('/auth')->group(__DIR__ . '/endpoints/auth.php');

Route::middleware('auth:sanctum')->get('/me', function(){
    //return response(null, 200);
    return auth()->user();
});
在我的 /endpoints/auth.php我有以下几点:
Route::post('/register', [UserController::class, "register"]);

Route::post('/login', [UserController::class, "login"]);

Route::middleware('auth:sanctum')->post('/logout', [UserController::class, 'logout']);
所以在上面的代码中,当我向 /api/me 发送请求时更改或删除我的 XSRF-TOKEN 后,我希望 token 不匹配,但实际上我得到了 200 OK 与经过身份验证的用户详细信息。
更新
我已经取得了一些进展。
我已将以下项目添加到 api 数组下的 App/Http/Kernel.php 中,如下所示:
'api' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
当我尝试提交登录请求时,我现在得到一个 HTTP 419,错误是 CSRF token 不匹配。
所以我已经取得了进展,它现在似乎正在尝试 CSRF 验证,但现在它总是说存在不匹配,即使它在请求中发送相同的 XSRF-TOKEN cookie。

最佳答案

我相信我已经弄清楚了,这部分与我的 HTTP 有关。休息客户端( Insomnia.Rest )但我在 ReactJS 上使用 axios 设置了一个测试项目并且遇到了同样的问题,但后来解决了。
部分原因是因为 Sanctums默认配置有点过时,其中一部分是加密 session/cookies而另一部分不是。
所以下config/session.php套装encrypt => trueApp\Http\Kernel.php将以下内容添加到 api middlewareGroups

\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
confif/cors.php套装support_credentials => trueconfig/session.php确保 SESSION_DRIVER是 cookies
另一个问题是对请求中发送的内容的误解。
当您收到 XSRF-TOKEN打电话时/sanctum/csrf-cookie我认为它只是作为 Insomnia 自动执行的 cookie 在请求中发送回。
不是这种情况。相反,您应该从 Insomnia 请求中提取 cookie,然后在每个 POST/PUT/DELETE 中提取 cookie。请求添加一个名为 X-XSRF-TOKEN 的新 header 到来自 sanctum 的 cookie 的值获取请求。
如果您使用的是 HTTP AXIOS 等前端项目的客户端,这是自动完成的,因此您无需担心。
下一个问题是 Insomnia.Rest我使用的 HTTP 客户端。
当我收到 XSRF-TOKEN Insomnia 将 cookie 存储在它的 cookie 存储中,但是,它们似乎对它进行了错误的编码,因此您会得到如下存储的 cookie 字符串:

eyJpdiI6Iml5YWEreGVaYUw0WGc2QmxlVEhQOGc9PSIsInZhbHVlIjoieVU2bmdyTjMyNFM0d0dnb3RsM24rMDFhRnJNWHVLcGg2SU9YMHh5dW8yaTZSTWcxbGxtSFdaK0I5MzB4Ymc4QWZWSzhjN2R6Y1RUTTc0d1VIY2FUaVhGMVE4bzQvWVBmL1YvajAwY3ZUNlZ4VEZIRk12cloyV0owVmNYOUxEZTIiLCJtYWMiOiI4OTUyN2U1MGI3NmUyMjEzZjgyNDcxMjAwYmViYjRkNzAwYmQ1YWUxOGY5NTYyNTVhZDczMmQ0ZjdlNjQwMGFhIn0%3D


请注意,最后它有 %3D,这是 = 符号的 URL 编码,因此 Laravel 得到了它并且无法与它期望的匹配。
因此,您需要编辑 cookie 以将 %3D 替换为 =,然后发送请求,它应该可以工作。
我还有一件奇怪的事情是,如果我发送带有 Referrer 和 Origin header 的请求,CSRF 验证会起作用,但是,如果我不这样做,则该请求会被接受,这对我来说似乎不正确,因为它有点像违背了 CSRF 保护的目的。

关于php - api 端点未在 Sanctum 上进行 CSRF token 验证 - CSRF token 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67970724/

相关文章:

ajax - chrome中跨域ajax POST

PHP IMagick RGB 到 CMYK 反转?

php - 调用未定义的方法 Laravel\Socialite\One\TwitterProvider::stateless()

php - Laravel 管理员 crud 项目

oop - 在不破坏其他部分的情况下重构代码的最佳设计模式

javascript - HttpClientXsrfModule 是否仍然需要在服务器上设置 XSRF-TOKEN?

node.js - 在 Express 中使用 csurf 和 session

javascript - 使用 php 对长文本进行分页

php - PDF 生成不保留样式表

php - mysql,查找父节点