VueJs 前端的无效 CSRF 令牌错误(symfony 5)

Posted

技术标签:

【中文标题】VueJs 前端的无效 CSRF 令牌错误(symfony 5)【英文标题】:Invalid CSRF token error ( symfony 5 ) with VueJs frontend 【发布时间】:2021-10-13 00:29:19 【问题描述】:

我在 symfony 应用程序中使用外部前端 (vue) 进行身份验证时遇到问题。主要问题是“无效的 CSRF 令牌”错误。我在 vue 中有一个登录表单,它发送一个包含用户名、密码和 csrf 令牌(我从 symfony tokengenerator 获得)的对象。我有一个自定义身份验证器,我在其中创建用户护照并将令牌添加到其中。

public function authenticate(Request $request): PassportInterface
    
        $username = $request->request->get('username', '');

        $request->getSession()->set(Security::LAST_USERNAME, $username);
        $this->logger->info('The token is', [$request->get('_csrf_token')]);
        $passport =  new Passport(
            new UserBadge($username),
            new PasswordCredentials($request->request->get('password', '')),
        );
        $passport->addBadge(new CsrfTokenBadge('authenticate', $request->get('_csrf_token'))); 
        return $passport;
    

它通过 AuthenticationManager.php 进入 executeAuthenticator 方法。在从 CSRFProtectionListener 调度 CheckPassportEvent 之后出现错误。它在 if (false === $this->csrfTokenManager->isTokenValid($csrfToken)).

我试图在我的身份验证器中获取令牌管理器实例并在那里创建令牌并将其添加到护照中。

$token = $this->csrfTokenManager->getToken('authenticate'); $passport->addBadge(new CsrfTokenBadge($token->getId(), $token->getValue()));

这让我通过了身份验证,但随后,当它重定向到下一个路径时,它给了我一个错误“访问被拒绝,用户未完全通过身份验证;重定向到身份验证入口点。”。经过一番调试,似乎token存储是空的(调用getToken()方法时token被保存到存储中)。

当我使用 twig 模板进行身份验证时,它可以完美运行。 csrf_token('authenticate') 究竟是如何制作和处理我不明白的令牌的。任何意见将不胜感激。

【问题讨论】:

【参考方案1】:

在 Symfony 5 中,您应该像这样使用 CSRF 保护: 在 Twig 中,您可以使用“csrf_token”方法生成 CSRF Token。此方法在此处描述https://symfony.com/doc/current/security/csrf.html#generating-and-checking-csrf-tokens-manually。

您可以使用“isCsrfTokenValid”函数验证控制器中的令牌,该函数位于您要扩展的控制器类中。

查看此处了解更多信息: https://symfony.com/doc/4.4/security/csrf.html#generating-and-checking-csrf-tokens-manually

我认为问题在于您使用的是新的 Symfony 版本,但使用的是旧的做法。

【讨论】:

就像我在问题中所说的那样,用树枝运行它没有问题。但我希望它与我在不同服务器上的 VueJs 前端一起工作。我在 symfony 5 中找不到任何解决此问题的相关指南。【参考方案2】:

您必须将 Authenticationintention 作为字符串传递。在您的示例中,它的“身份验证”。

$passport->addBadge(new CsrfTokenBadge(' ---> authenticate <--- ', $request->get('_csrf_token'))); 

要检查它,您应该使用如下代码:

if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken('authenticate' $YOUR_TOKEN_HERE))

或来自控制器:

$this->isCsrfTokenValid('authenticate', $YOUR_TOKEN_HERE)
enter code here

【讨论】:

当我默认使用 ->get('_csrf_token') 时,isTokenValid 总是返回 false。在我的控制器中,我使用以下代码将令牌发送到 vue:` public function GenerateToken() $token = $this->tokenGenerator->generateToken();返回新的响应(json_encode($token)); ` 因此,如果我在后端生成令牌,将其发送到 vue,然后与表单一起提交,isTokenValid 方法总是返回 false(即使我在令牌管理器中实现随机化)。如果我在身份验证器中生成令牌,则登录有效,但是向任何其他控制器发出任何请求都会返回一个错误,即用户未完全通过身份验证,这似乎是因为它找不到用户的会话(返回 null ) . 你真的使用 symfony 5 吗?您的代码,尤其是您收集服务的部分(无 dep 注入)似乎已经过时了。

以上是关于VueJs 前端的无效 CSRF 令牌错误(symfony 5)的主要内容,如果未能解决你的问题,请参考以下文章

CSRF 令牌不匹配错误,Laravel 5.3/VueJS2

Symfony3 中的错误“CSRF 令牌无效。请尝试重新提交表单”

在nodejs(Express)中使用CSURF的“无效的csrf令牌”。CSRF令牌适用于第一个请求,但对所有其他请求都给出错误

上传时出现 HTTP 403 错误 - 无效的 CSRF 令牌“空”

在测试中获取 CSRF 令牌,“CSRF 令牌无效” - 功能性 ajax 测试

Symfony:身份验证请求失败:无效的 CSRF 令牌