Symfony - 使用 LexikJWTAuthenticationBundle 设置 TokenController
Symfony - Setup the TokenController with LexikJWTAuthenticationBundle
我正在使用 LexikJWTAuthenticationBundle https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/index.md#installation
我正在设置我的控制器以获取令牌:
class TokenController extends AbstractController
{
/**
* @Route("/api/token", name="token", methods={"POST"})
* @param Request $request
* @param JWTEncoderInterface $JWTEncoder
* @return JsonResponse
* @throws \Lexik\Bundle\JWTAuthenticationBundle\Exception\JWTEncodeFailureException
*/
public function token(Request $request, JWTEncoderInterface $JWTEncoder)
{
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy([
'email' => $request->getUser(),
]);
if (!$user) {
throw $this->createNotFoundException('User Not Found');
}
$isValid = $this->get('security.password_encoder')
->isPasswordValid($user, $request->getPassword());
if (!$isValid) {
throw new BadCredentialsException();
}
$token = $JWTEncoder->encode([
'email' => $user->getEmail(),
'exp' => time() + 3600 // 1 hour expiration
]);
return new JsonResponse(['token' => $token]);
}
}
但是我有这个错误:
Service "security.password_encoder" not found: even though it exists
in the app's container, the container inside
"App\Controller\TokenController" is a smaller service locator that
only knows about the "doctrine", "form.factory", "http_kernel",
"parameter_bag", "request_stack", "router",
"security.authorization_checker", "security.csrf.token_manager",
"security.token_storage", "serializer", "session" and "twig" services.
Unless you need extra laziness, try using dependency injection
instead. Otherwise, you need to declare it using
"TokenController::getSubscribedServices()".
我使用了依赖注入,这是我的服务配置文件
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
问题出在哪里?
您正在使用此控制器从 AbstractController
扩展,您使用 $this->get()
访问的服务将受到限制。要访问密码编码器服务,您可以将 Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface
注入控制器操作或通过控制器 class 构造函数。
private $passwordEncoder;
public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}
...
$this->passwordEncoder->isPasswordValid()
...
或者您可以从 Symfony\Bundle\FrameworkBundle\Controller\Controller
扩展以获得完整的容器访问权限。 $this->get('security.password_encoder')
应该适用于此。
我正在使用 LexikJWTAuthenticationBundle https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/index.md#installation
我正在设置我的控制器以获取令牌:
class TokenController extends AbstractController
{
/**
* @Route("/api/token", name="token", methods={"POST"})
* @param Request $request
* @param JWTEncoderInterface $JWTEncoder
* @return JsonResponse
* @throws \Lexik\Bundle\JWTAuthenticationBundle\Exception\JWTEncodeFailureException
*/
public function token(Request $request, JWTEncoderInterface $JWTEncoder)
{
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy([
'email' => $request->getUser(),
]);
if (!$user) {
throw $this->createNotFoundException('User Not Found');
}
$isValid = $this->get('security.password_encoder')
->isPasswordValid($user, $request->getPassword());
if (!$isValid) {
throw new BadCredentialsException();
}
$token = $JWTEncoder->encode([
'email' => $user->getEmail(),
'exp' => time() + 3600 // 1 hour expiration
]);
return new JsonResponse(['token' => $token]);
}
}
但是我有这个错误:
Service "security.password_encoder" not found: even though it exists in the app's container, the container inside "App\Controller\TokenController" is a smaller service locator that only knows about the "doctrine", "form.factory", "http_kernel", "parameter_bag", "request_stack", "router", "security.authorization_checker", "security.csrf.token_manager", "security.token_storage", "serializer", "session" and "twig" services. Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "TokenController::getSubscribedServices()".
我使用了依赖注入,这是我的服务配置文件
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
问题出在哪里?
您正在使用此控制器从 AbstractController
扩展,您使用 $this->get()
访问的服务将受到限制。要访问密码编码器服务,您可以将 Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface
注入控制器操作或通过控制器 class 构造函数。
private $passwordEncoder;
public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}
...
$this->passwordEncoder->isPasswordValid()
...
或者您可以从 Symfony\Bundle\FrameworkBundle\Controller\Controller
扩展以获得完整的容器访问权限。 $this->get('security.password_encoder')
应该适用于此。