Php 带有JWT的Symfony 5防火墙阻止对某些路由的访问,而无需登录
我用它来管理令牌创建和所有的jazz 我的Php 带有JWT的Symfony 5防火墙阻止对某些路由的访问,而无需登录,php,symfony,jwt,Php,Symfony,Jwt,我用它来管理令牌创建和所有的jazz 我的security.yaml文件如下所示(删除了不相关的内容): 就JWT而言,它工作正常 做一个简单的卷曲 $ curl -X POST -H "Content-Type: application/json" http://localhost/api/\login_check -d '{"username":"someusername","password":"somepassword!"}' 返回一个令牌: % Total % Receiv
security.yaml
文件如下所示(删除了不相关的内容):
就JWT而言,它工作正常
做一个简单的卷曲
$ curl -X POST -H "Content-Type: application/json" http://localhost/api/\login_check -d '{"username":"someusername","password":"somepassword!"}'
返回一个令牌:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 910 100 852 100 58 376 25 0:00:02 0:00:02 --:--:-- 376
{"token":"6wvL6E..."}
问题是,每隔一条路由就会响应一个302
,该路由会立即重定向到/
Request URL: http://localhost/register
Request Method: GET
Status Code: 302 Found
Remote Address: [::1]:80
Referrer Policy: no-referrer-when-downgrade
很明显我在什么地方配置错了。但我似乎找不到。就我而言,配置似乎很好 也许有人比我有更好的眼光(和更好的经验)可以帮我一把 我只能假设JWT期望
X
route有一个令牌,但是,我显然在访问控制中列出了某些路径
删除捆绑包并恢复任何更改将使所有路由按预期运行
经过进一步调查,它似乎与定制的LoginFormAuthenticator
<?php
namespace App\Security;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements PasswordAuthenticatedInterface
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
public function supports(Request $request)
{
return 'login_user' === $request->attributes->get('_route') && $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function getPassword($credentials): ?string
{
return $credentials['password'];
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('index', [], RouterInterface::ABSOLUTE_URL));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('login_user');
}
}
因此,在您的配置中,您有一个带有自定义LoginFormAuthenticator的主防火墙,在该防火墙中,我看不到当您使用时,登录不需要验证器的全部要点
我还注意到,如果您向它发出请求(例如),它将使用LoginFormAuthenticator,而LoginFormAuthenticator将不支持该请求,因为在它的supports()函数中,您声明接受某些路由
return 'login_user' === $request->attributes->get('_route') ....
另一个可以排除故障的是onAuthenticationSuccess函数,尤其是我对这一行有怀疑
return new RedirectResponse($this->urlGenerator->generate('index', [], RouterInterface::ABSOLUTE_URL));
我假设您有一个名为index的路由,它有路径“/”,如果您使用routes.yaml,它看起来像这样。(其他类型中也有相同的原则)
因此,基本上是告诉验证器重定向到“/”。那将是我的另一个猜测。
我希望我能提供帮助。经过几个小时痛苦的调试,我发现会话由于任何原因被挂起。最后,我对会话存储介质(在我的例子中是数据库)进行了一次完全擦除。我认为这与包裹本身无关。很可能symfony在某个地方默默地搞砸了。我尝试实现类似的逻辑,得到了类似的结果,这让我思考,我检查了一下,它解决了我的问题-。我现在很好奇是什么导致了symfony的崩溃。
return new RedirectResponse($this->urlGenerator->generate('index', [], RouterInterface::ABSOLUTE_URL));
index:
path: /
controller: App\Controller\ACMEController::fooFunction