如何在Symfony Messenger中使用投票者/权限?[关闭]

uqdfh47h  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(116)

已关闭,此问题为opinion-based,目前不接受回答。
**想改进这个问题吗?**更新问题,以便editing this post可以用事实和引用来回答。

三年前就关门了。
Improve this question
我正在开发一个应用程序,有一个安装的Symfony Messenger组件来处理BTC消息。消息的处理程序需要检查一些特定用户的一些权限,如如果一个确定的用户应该收到一封电子邮件,如果有编辑权限的信息,例如。
为了实现这一点,我们使用Symfony投票者,但当我们没有任何用户登录到系统,如在控制台命令和EQUAC消息是非常烦人的。什么是最好的解决方案?
非常感谢你

kqqjbcuj

kqqjbcuj1#

我可能更喜欢在发送消息之前检查用户的权限,但是让我们想想如果这不是一个合适的情况,我们该如何处理。
为了检查用户权限,您需要验证用户。但是如果您异步消费消息或执行控制台命令,这并不简单,因为您没有实际的用户。但是,您可以将用户id与消息一起传递或传递给控制台命令。
让我来分享一下我对Symfony Messenger的一个简单解决方案的想法。在Symfony Messenger中,有一个Stamps的概念,它允许您将元数据添加到消息中。在我们的例子中,将用户ID与消息一起传递会很有用,这样我们就可以在消息处理过程中验证用户。
让我们创建一个自定义的stamp来保存用户ID。这是一个简单的PHP类,所以不需要将其注册为服务。

<?php

namespace App\Messenger\Stamp;

use Symfony\Component\Messenger\Stamp\StampInterface;

class AuthenticationStamp implements StampInterface
{
    private $userId;

    public function __construct(string $userId)
    {
        $this->userId = $userId;
    }

    public function getUserId(): string
    {
        return $this->userId;
    }
}

现在我们可以将戳添加到消息中。

$message = new SampleMessage($payload);
$this->messageBus->dispatch(
    (new Envelope($message))
        ->with(new AuthenticationStamp($userId))
);

我们需要接收和处理stamp来验证用户。Symfony Messenger有一个中间件的概念,所以让我们创建一个中间件来处理stamp,当我们收到一个worker的消息时。它会检查消息是否包含AuthenticationStamp,如果用户目前没有通过身份验证,则对用户进行身份验证。

<?php

namespace App\Messenger\Middleware;

use App\Messenger\Stamp\AuthenticationStamp;
use App\Repository\UserRepositoryInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class AuthenticationMiddleware implements MiddlewareInterface
{
    private $tokenStorage;
    private $userRepository;

    public function __construct(TokenStorageInterface $tokenStorage, UserRepositoryInterface $userRepository)
    {
        $this->tokenStorage = $tokenStorage;
        $this->userRepository = $userRepository;
    }

    public function handle(Envelope $envelope, StackInterface $stack): Envelope
    {
        /** @var AuthenticationStamp|null $authenticationStamp */
        if ($authenticationStamp = $envelope->last(AuthenticationStamp::class)) {
            $userId = $authenticationStamp->getUserId();

            $token = $this->tokenStorage->getToken();
            if (null === $token || $token instanceof AnonymousToken) {
                $user = $this->userRepository->find($userId);
                if ($user) {
                    $this->tokenStorage->setToken(new UsernamePasswordToken(
                        $user,
                        null,
                        'provider',
                        $user->getRoles())
                    );
                }
            }
        }

        return $stack->next()->handle($envelope, $stack);
    }
}

让我们将其注册为一个服务(或autowire),并将其包含到messenger配置定义中。

framework:
  messenger:
    buses:
      messenger.bus.default:
        middleware:
          - 'App\Messenger\Middleware\AuthenticationMiddleware'

差不多就是这样了。现在你应该可以使用常规的方法来检查用户的权限,例如,投票者。
至于控制台命令,我会选择一个身份验证服务,如果用户id被传递给一个命令,它将对用户进行身份验证。

相关问题