我的应用程序上有多个防火墙,对于其中一个,我需要在symfony
登录表单上再添加一个字段。
除了username
和password
之外,我还需要恢复用户必须填写的字段"code"
才能登录此防火墙。
我在官方symfony
文档中看到了这一点:
https://symfony.com/doc/current/security/custom_password_authenticator.html
但是我不知道如何处理表单中的新字段。
我不使用fosuserbundle
,也不需要使用它。
这是为认证系统创建自定义表单登录名的symfony
建议
// src/Security/TimeAuthenticator.php
namespace App\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Authentication\SimpleFormAuthenticatorInterface;
class TimeAuthenticator implements SimpleFormAuthenticatorInterface
{
private $encoder;
public function __construct(UserPasswordEncoderInterface $encoder)
{
$this->encoder = $encoder;
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
try {
$user = $userProvider->loadUserByUsername($token->getUsername());
} catch (UsernameNotFoundException $exception) {
// CAUTION: this message will be returned to the client
// (so don't put any un-trusted messages / error strings here)
throw new CustomUserMessageAuthenticationException('Invalid username or password');
}
$currentUser = $token->getUser();
if ($currentUser instanceof UserInterface) {
if ($currentUser->getPassword() !== $user->getPassword()) {
throw new BadCredentialsException('The credentials were changed from another session.');
}
} else {
if ('' === ($givenPassword = $token->getCredentials())) {
throw new BadCredentialsException('The given password cannot be empty.');
}
if (!$this->encoder->isPasswordValid($user, $givenPassword)) {
throw new BadCredentialsException('The given password is invalid.');
}
}
$currentHour = date('G');
if ($currentHour < 14 || $currentHour > 16) {
// CAUTION: this message will be returned to the client
// (so don't put any un-trusted messages / error strings here)
throw new CustomUserMessageAuthenticationException(
'You can only log in between 2 and 4!',
array(), // Message Data
412 // HTTP 412 Precondition Failed
);
}
return new UsernamePasswordToken(
$user,
$user->getPassword(),
$providerKey,
$user->getRoles()
);
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof UsernamePasswordToken
&& $token->getProviderKey() === $providerKey;
}
public function createToken(Request $request, $username, $password, $providerKey)
{
return new UsernamePasswordToken($username, $password, $providerKey);
}
}
在此示例中,没有多余的字段恢复。
这是symfony
身份验证的默认表单登录名,我目前正在使用它:
<form action="{{ path('login') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
{#
If you want to control the URL the user
is redirected to on success (more details below)
<input type="hidden" name="_target_path" value="/account" />
#}
<button type="submit">login</button>
</form>
我想在此表单中添加一个字段,并在我的自定义SimpleFormAuthenticatorInterface
中恢复它以执行身份验证逻辑,我需要这个额外的字段。
预先感谢您的建议。
答案 0 :(得分:1)
要将其他请求参数获取到类中,可以将RequestStack
注入到TimeAuthenticator
中:
class TimeAuthenticator implements SimpleFormAuthenticatorInterface
{
private $encoder;
private $requestStack;
public function __construct(RequestStack $requestStack, UserPasswordEncoderInterface $encoder)
{
$this->requestStack = $requestStack;
$this->encoder = $encoder;
}
public function getOneTimeToken() : ?string
{
$this->requestStack->getCurrentRequest()->request->get('yourNewField', null);
}
//...
然后使用新方法通过authenticateToken()
方法针对用户检查提交的值。
还请检查GuardAuthenticator系统,因为它更适合您的需求。