关于Badge属性,以前比较陌生,但是最近项目开发过程中,有时用到,就特意记录一下.
这是Passport的一个属性,主要是为了给Passport添加额外的信息.
先看之前写的 Authenticator
$res = $this->userPasswordHasher->isPasswordValid(
$this->em->getRepository(User::class)->findOneBy(['email' => $username]),
$request->request->get('password', '')
);
if ($res){
// 通过闭包获取用户信息,这个地方 UserBadge 后面可以传递一个闭包 返回User
return new SelfValidatingPassport(new UserBadge($username, function ($email){
return $this->em->getRepository(User::class)->findOneBy(['email' => $email]);
}), [new LoginPlatformBadge('pc')]);
}else{
throw new BadCredentialsException('invalid email or password.');
}
还可以直接通过 Passport 对象处理数据:
return new Passport(
new UserBadge($username),
new PasswordCredentials($password),
[new LoginPlatformBadge('pc')]
);
可以看到我在上面都加了 自定义的 LoginPlatformBadge,这个就是给 Passport 一个附加属性,因为上面的Passport 会 触发 CheckPassportEvent(这是symfony内置的事件,相关事件还有好几个),所以 我们可以监听这个事件
LoginPlatformSubscriber:
<?php
namespace App\EventSubscriber;
use App\Security\LoginPlatformBadge;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\CheckPassportEvent;
class LoginPlatformSubscriber implements EventSubscriberInterface
{
public function onCheckPassportEvent(CheckPassportEvent $event): void
{
$passport = $event->getPassport();
/** @var LoginPlatformBadge $badge */
$badge = $passport->getBadge(LoginPlatformBadge::class);
if (null === $badge || $badge->isResolved()) {
return;
}
dump($badge->getPlatform().time());
/**
* 这里可以针对不同的 platform 做不同的逻辑操作
*/
/**
* 最后记得把这个 badge 设置为 解析过 状态
*/
$badge->markResolved();
}
public static function getSubscribedEvents(): array
{
// 因为上面的 Passport 最终会触发 CheckPassportEvent 这个事件,所以我们需要 设置一个监听
// TODO: Implement getSubscribedEvents() method.
return [
CheckPassportEvent::class => 'onCheckPassportEvent',
];
}
}
LoginPlatformBadge:
<?php
namespace App\Security;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
class LoginPlatformBadge implements BadgeInterface
{
private bool $resolved = false;
public function __construct(
private string $platform,
){}
public function isResolved(): bool
{
// TODO: Implement isResolved() method.
return $this->resolved;
}
public function markResolved():void{
$this->resolved = true;
}
public function getPlatform():string{
return $this->platform;
}
}
