我想在我的自定义登录身份验证中(使用SimpleForm)使用ConstraintValidator来验证此捆绑包的Google Recaptcha EWZRecaptchaBundle我不知道
security.yaml
主要防火墙部分:
providers:
default:
entity:
class: App:User
property: phone
main:
pattern: ^/
anonymous: ~
provider: default
simple_form:
authenticator: App\Security\Authenticator\UserAuthenticator
check_path: login
login_path: login
username_parameter: phone
password_parameter: password
use_referer: true
logout:
path: logout
我需要在App\Security\Authenticator\UserAuthenticator
中使用Validaitor
这是我的自定义身份验证者(App\Security\Authenticator\UserAuthenticator
):
//...
class UserAuthenticator 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) {
throw new CustomUserMessageAuthenticationException("invalid");
}
$isPasswordValid = $this->encoder->isPasswordValid($user, $token->getCredentials());
if ($isPasswordValid) {
return new UsernamePasswordToken($user, $user->getPassword(), $providerKey, $user->getRoles());
}
throw new CustomUserMessageAuthenticationException("invalid");
}
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);
}
}
答案 0 :(得分:1)
请查看How to Create a Custom Authentication System with Guard,以更简单,更灵活的方式完成此类自定义身份验证任务。
特别是您将创建的 GuardAuthenticator 类的 getCredentials 方法。
getCredentials(请求$ request) 将在每个请求上调用此方法,您的工作是从请求中读取令牌(或任何“身份验证”信息)并返回它。这些凭据随后作为getUser()的第一个参数传递。
或您的任何“身份验证”信息,因此您将能够处理在验证码中传递的值。
<?php
namespace App\Security\Authenticator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Validator\Validator\Validator\ValidatorInterface;
class FormLoginAuthenticator extends AbstractFormLoginAuthenticator
{
/**
* @var UserPasswordEncoderInterface
*/
private $encoder;
/**
* @var ValidatorInterface
*/
private $validator;
/**
* FormLoginAuthenticator constructor.
* @param UserPasswordEncoderInterface $encoder
* @param IsTrueValidator $isTrueValidator
*/
public function __construct(UserPasswordEncoderInterface $encoder, ValidatorInterface $validator)
{
$this->encoder = $encoder;
$this->validator = $validator;
}
/**
* Return the URL to the login page.
*
* @return string
*/
protected function getLoginUrl()
{
return '/login';
}
/**
* Does the authenticator support the given Request?
*
* If this returns false, the authenticator will be skipped.
*
* @param Request $request
*
* @return bool
*/
public function supports(Request $request)
{
return true;
}
/**
*
* @param Request $request
*
* @return mixed Any non-null value
*
* @throws \UnexpectedValueException If null is returned
*/
public function getCredentials(Request $request)
{
$violations = $this->validator->validate($request->request->get('g-recaptcha-response'), new IsTrue());
if($violations->count() > 0){
throw new AuthenticationException(self::INVALID_RECAPTCHA);
}
return array(
'username' => $request->request->get('_username'),
'password' => $request->request->get('_password'),
);
}
/**
* Return a UserInterface object based on the credentials.
*
* The *credentials* are the return value from getCredentials()
*
* You may throw an AuthenticationException if you wish. If you return
* null, then a UsernameNotFoundException is thrown for you.
*
* @param mixed $credentials
* @param UserProviderInterface $userProvider
*
* @throws AuthenticationException
*
* @return UserInterface|null
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $userProvider->loadUserByUsername($credentials['username']);
}
/**
* Returns true if the credentials are valid.
*
* If any value other than true is returned, authentication will
* fail. You may also throw an AuthenticationException if you wish
* to cause authentication to fail.
*
* The *credentials* are the return value from getCredentials()
*
* @param mixed $credentials
* @param UserInterface $user
*
* @return bool
*
* @throws AuthenticationException
*/
public function checkCredentials($credentials, UserInterface $user)
{
$plainPassword = $credentials['password'];
if (!empty($plainPassword) && !$this->encoder->isPasswordValid($user, $plainPassword)) {
throw new BadCredentialsException();
}
return true;
}
/**
* Called when authentication executed and was successful!
*
* If you return null, the current request will continue, and the user
* will be authenticated. This makes sense, for example, with an API.
*
* @param Request $request
* @param TokenInterface $token
* @param string $providerKey The provider (i.e. firewall) key
*
* @return Response|null
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
return null;
}
}
确保您的身份验证者已注册为服务。如果您使用的是default services.yaml配置,则会自动发生。因此,您还可以在GuardAuthenticator的构造函数中传递EWZRecaptchaBundle验证程序,然后可以在发送 getCredentials
中的用户名和密码之前,使用它来验证Recaptcha值。并像这样更改security.yaml:
providers:
default:
entity:
class: App:User
property: phone
main:
pattern: ^/
anonymous: ~
provider: default
guard:
authenticators:
- App\Security\FormLoginAuthenticator
logout: ~