【发布时间】:2021-08-30 09:18:20
【问题描述】:
我目前正在学习 Laravel(进展不是特别顺利),并且我已经配置了一些路由来测试使用 sanctum 的身份验证。
我正在构建一个仅 API 的 laravel 服务,并计划让 ReactJS 项目使用该 API。
我目前虽然没有使用 ReactJS 并使用 Insomnia REST 客户端来测试 API。
我有一个用于注册新用户、登录的路由,然后是另一个仅返回经过身份验证的用户以证明身份验证机制正常工作的路由。
我对 CSRF 不太了解,但我的理解是我请求一个新的 CSRF 令牌,然后对 API 的每个请求都使用这个 CSRF 令牌,例如,当我登录然后从相应的路由,CSRF token cookie 也会被发送,因此如果发送不同的 CSRF token,我应该会得到 token mismatch 错误。
我正在通过向 /sanctum/csrf-cookie 发送请求来使用 Insomnia 对此进行测试,该请求返回给我一个 204 并且 Insomnia 设置了 3 个 cookie,其中一个是 XSRF-TOKEN,我理解它是 CSRF 的加密形式令牌。
然后我成功登录,然后当我调用我的路由以获取经过身份验证的用户时,我修改或删除 XSRF-TOKEN cookie 并发送请求,然后我希望收到关于令牌不匹配的错误但是这个似乎不是这样,我得到了有效的回复。
下面是我的 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']);
因此,在上面的代码中,当我在更改或删除我的 XSRF-TOKEN 后向/api/me 发送请求时,我预计令牌不匹配,但实际上我得到了经过身份验证的用户详细信息的 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 令牌不匹配。
所以我已经取得了进展,它现在似乎正在尝试 CSRF 验证,但现在它总是说存在不匹配,即使它在请求中发送相同的 XSRF-TOKEN cookie。
【问题讨论】:
-
检查您是否没有通过其他来源发送令牌,例如
_token标头的_token表单字段 -
@apokryfos 抱歉,我不确定我是否关注,我没有从表单发送,因为我使用的是 REST 测试客户端,请求中没有发送正文数据
-
我不确定您是否会在默认情况下为 API 路由获得 CSRF 保护,因为它通过会话工作。检查您的
VerifyCsrfToken中间件是否排除了 api 路由(它们通常应该是)。如果您使用会话,请尝试在 web.php 中移动您的路线,如果您使用 Laravel 作为 API,请不要使用 CSRF 令牌 -
我认为 Laravel API(或一般的 API)应该有 CSRF 保护。 Sanctum 目前正在使用基于令牌的身份验证。 VerifyCsrfToken 中的 except 数组中没有任何内容,它只是一个空数组。如果我将路由移动到 web.php 对 Laravel 前端来说不是更多,所以我不会使用 /api 路径?
-
API 通常不需要(甚至不可能)CSRF,因为从本质上讲,所有请求都被认为是跨站点的。从 API 读取时,通常不希望存储和传输 Cookie,因为 Cookie 更像是浏览器的东西,其余客户端需要额外设置才能正确存储它们
标签: php laravel csrf laravel-sanctum