我需要根据此算法在我的一个Symfony 2项目中实现双向身份验证过程:
md5(password)
。我已经有一个服务可以使用外部API通过他的用户名和密码来调用用户,我只是想在验证过程中使用它。
实现此行为的最简单方法是什么?我只需指出正确的方向。
正在实施" custom authenticator"这个问题是一个很好的解决方案吗?或者有更好的方法吗?
查看文档,我将在自定义身份验证器中实现两个身份验证步骤。是否有可能只实施额外的步骤?
答案 0 :(得分:0)
是的,这是要走的路。如果您的Web服务只能通过用户名为您提供用户,那么您只能在UserProvider中执行此操作,因为在其范围内您只有用户名。如果您必须通过un / pw查询,那么您必须在身份验证器中进行查询,因为在该范围内您有密码。因此,使用简单的形式,它将看起来像这样
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
try {
$user = $userProvider->loadUserByUsername($token->getUsername());
} catch (UsernameNotFoundException $e) {
throw new AuthenticationException('Invalid username or password');
}
$encoder = $this->encoderFactory->getEncoder($user);
$passwordValid = $encoder->isPasswordValid(
$user->getPassword(),
$token->getCredentials(),
$user->getSalt()
);
if ($passwordValid) {
return new UsernamePasswordToken(
$user,
$user->getPassword(),
$providerKey,
$user->getRoles()
);
}
// remote users fallback
$webUser = $this->externalUserService->getByUsernamePassword(
$token->getUsername(),
$token->getCredentials()
);
if ($webUser) {
return new UsernamePasswordToken(
$webUser,
$token->getCredentials(),
$providerKey,
$webUser->getRoles()
);
}
throw new AuthenticationException('Invalid username or password');
}
Ofc在这个类中有太多的ifs并且它负责多于一件事,所以要整洁你可以应用复合模式并且有3个验证器,一个通用复合器,第二个本地db验证器和第三个外部服务验证器,以及从像这样的服务配置构建它。
# services.yml
my_app.authenticator.main:
class: MyApp/Security/Core/Authentication/CompisiteAuthenticator
calls:
- [ add, [@my_app.authenticator.locale]]
- [ add, [@my_app.authenticator.remote]]
my_app.authenticator.locale:
class: MyApp/Security/Core/Authentication/LocalAuthenticator
arguments: [@security.encoder_factory]
my_app.authenticator.remote:
class: MyApp/Security/Core/Authentication/RemoteAuthenticator
arguments: [@my_app.remote_user_service]
复合
<?php
namespace MyApp/Security/Core/;
class CompositeAuthenticator implements SimpleFormAuthenticatorInterface
{
/** @var SimpleFormAuthenticatorInterface[] */
protected $children = array();
public function add(SimpleFormAuthenticatorInterface $authenticator)
{
$this->children[] = $authenticator;
}
public function createToken(Request $request, $username, $password, $providerKey)
{
return new UsernamePasswordToken($username, $password, $providerKey);
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof UsernamePasswordToken
&& $token->getProviderKey() === $providerKey;
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
$result = null;
foreach ($this->children as $authenticator)
{
$result = $authenticator->authenticateToken($token, $userProvider, $providerKey);
if ($result) {
return $result;
}
}
throw new AuthenticationException('Invalid username or password');
}
}
我认为本地和远程身份验证器是微不足道的