Authentication Symfony:为什么一些用户检查应该在身份验证之后执行?

Authentication Symfony:为什么一些用户检查应该在身份验证之后执行?,authentication,symfony,Authentication,Symfony,我不明白UserCheckerInterface有两种方法:checkPreAuth和checkPostAuth。现在让我们看看它们在类UserChecker中的实现: class UserChecker implements UserCheckerInterface { /** * {@inheritdoc} */ public function checkPreAuth(UserInterface $user) { if (!$us

我不明白
UserCheckerInterface
有两种方法:
checkPreAuth
checkPostAuth
。现在让我们看看它们在类
UserChecker
中的实现:

class UserChecker implements UserCheckerInterface
{
    /**
     * {@inheritdoc}
     */
    public function checkPreAuth(UserInterface $user)
    {
        if (!$user instanceof AdvancedUserInterface) {
            return;
        }

        if (!$user->isAccountNonLocked()) {
            $ex = new LockedException('User account is locked.');
            $ex->setUser($user);
            throw $ex;
        }

        if (!$user->isEnabled()) {
            $ex = new DisabledException('User account is disabled.');
            $ex->setUser($user);
            throw $ex;
        }

        if (!$user->isAccountNonExpired()) {
            $ex = new AccountExpiredException('User account has expired.');
            $ex->setUser($user);
            throw $ex;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function checkPostAuth(UserInterface $user)
    {
        if (!$user instanceof AdvancedUserInterface) {
            return;
        }

        if (!$user->isCredentialsNonExpired()) {
            $ex = new CredentialsExpiredException('User credentials have expired.');
            $ex->setUser($user);
            throw $ex;
        }
    }
}

为什么要在身份验证后执行
isCredentialsNonExpired()
?我们不应该只允许具有过期凭据的用户进行身份验证吗?还有一个额外的问题:我们应该在哪里进行这种“认证后”检查?设置身份验证令牌后?

我认为方法被拆分的原因是,当使用基于会话的身份验证时,有些事情您不想每次都检查

使用会话时,Symfony将序列化令牌(和相关用户)。当下一个请求传入时,预验证的令牌将包含授权所需的凭据

预认证令牌的一些示例如下:(从中被盗)

  • 基于“记住我”cookie的身份验证
  • 基于会话的身份验证
  • 使用HTTP基本或HTTP摘要标头进行身份验证
如果会话中存储了令牌,则可以删除一些检查以提高性能。我仅有的
UserCheckerInterface
示例是Symfony提供的。如您所见,用户帐户的验证是在
preAuth
中完成的,而
postAuth
仅检查凭据是否已过期

在实际案例中,查看使用这些方法的服务,您可以看到它们之间并没有太大区别。
GuardAuthenticationProvider
顺序调用这两个函数

Symfony的
预身份验证DauthenticationProvider
仅调用
后身份验证
,因此,Symfony中可能有人决定,为了使基于会话的身份验证缩短几毫秒的响应时间,他们可以将需要在首次身份验证时进行的身份验证检查与需要在首次身份验证时进行的身份验证检查分开每一个请求


在您的情况下,如果您正在创建一个自定义的
UserChecker
,我想您可以自己决定是否需要同时使用这两个工具。了解是否有其他包的身份验证提供程序调用这些方法之一。找到调用它们的所有位置,您可能会发现您只需要实现一个,或者,如果您有很多复杂的身份验证逻辑,则将其拆分。

我猜
checkPostAuth
用于
凭证
,它们不是
身份验证的一部分,而是
授权的一部分。这通常是在用户身份验证之后。不过不确定。哦,这很有意义,所以我应该在我的“身份验证服务”(如果我创建了一个)中使用这两种方法来检查登录时的所有内容,并在每个请求中使用
postAuth
方法来确保用户的令牌仍然有效?我这里有一个小问题-哪里是运行
postAuth
方法的好地方?在
kernel.request
event上(我不确定这一点,因为我想这个事件也会在子请求上运行,这会过多)?这取决于您正在构建什么。如果它是一个身份验证提供商,我无法更好地解释它,但如果它是一个用户检查服务,那么我想象它将与您正在使用的任何身份验证提供商集成。在这种情况下,您将用自定义UserChecker替换UserCheckerInterface参数。我正在构建自己的“用户包”以供学习,所以我只是想了解一下这一点。通过“身份验证服务”,我想到了一个“登录管理器”,即为用户创建和设置身份验证令牌的服务。据我所知,在这个登录管理器中,在为用户设置身份验证令牌之前进行用户检查是一个好主意。但我只是想知道,对于已经拥有代币并正在发出请求的用户来说,哪里是放置
postAuth
支票的最佳位置。但我想这是我现在要做的,因为这完全是可选的。我认为在你的情况下,如果你创建一个完全定制的身份验证提供者,这可能是可选的。我认为身份验证提供者的想法不是创建令牌,而是对令牌进行身份验证(找出它是哪个用户)。symfony docs示例中的令牌是在
getResponseEvent
的侦听器中创建的。如果您确实想将身份验证和用户检查分开,我建议创建一个身份验证提供程序,让用户检查用户,并在提供无效用户时抛出异常。多亏了您的提示,我认为通过分析Symfony core,我终于得到了它。RememberMe auth provider仅使用
checkPreAuth
,如果您仔细考虑的话-这非常有意义,因为当您使用RememberMeToken登录时-您的登录与您的凭据无关,因此您不必执行凭据检查。您可能需要更改凭据,但这不一定会干扰“记住我”功能。:)