Добавление капчи на страницу входа в Symfony2Php

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Добавление капчи на страницу входа в Symfony2

Сообщение Anonymous »

Я новичок в Symfony2, но много читал об этом.
Прежде всего, я использую Symfony 2.1.7. И FOSUserBundle для пользовательских настроек. Я уже переопределил шаблон fos_user-login с именем пользователя и паролем. Но я хочу добавить капчу для входа в систему. Я видел GregwarCaptchaBundle, и согласно документу, в FormType должно быть добавлено новое поле. И у меня возникает вопрос: где находится тип формы входа в систему symfony или FOSUserBundle, в который я могу добавить это новое поле или переопределить его? Существует ChangePasswordFormType, ProfileFormType... и т. д., но нет LoginFOrmType. Может быть, это так очевидно, но я не понял сути. Любая помощь приветствуется, пожалуйста.

ВОПРОС КАК-ТО РЕДАКТИРОВАНО С РЕШЕНИЕМ

Возьмите посмотрите комментарии ниже, Патт помог мне.
Я создал новый тип формы с полями _username, _password и captcha. Когда имя пользователя и пароль начинаются с подчеркивания, этого достаточно для маршрутизации «login_check» и аутентификации Symfony. Однако Symfony использует прослушиватель для процесса входа в систему.
Это класс UsernamePasswordFormAuthenticationListener. Хотя я добавил поле капчи в тип формы, оно всегда игнорируется во время процесса входа в систему. (Оно отображается на странице, но поле никогда не проверяется, оно просто игнорируется.)

Код: Выделить всё

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('_username', 'email', array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle')) // TODO: user can login with email by inhibit the user to enter username
->add('_password', 'password', array(
'label' => 'form.current_password',
'translation_domain' => 'FOSUserBundle',
'mapped' => false,
'constraints' => new UserPassword()))
->add('captcha', 'captcha');
}
Как я уже упоминал выше, класс UsernamePasswordFormAuthenticationListener получает входные значения формы, а затем перенаправляет вас:

Код: Выделить всё

public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfProviderInterface $csrfProvider = null)
{
parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array(
'username_parameter' => '_username',
'password_parameter' => '_password',
'csrf_parameter'     => '_csrf_token',
'captcha'           => 'captcha',
'intention'          => 'authenticate',
'post_only'          => true,
), $options), $logger, $dispatcher);

$this->csrfProvider = $csrfProvider;
}
Добавлено поле для ввода капчи.

Код: Выделить всё

protected function attemptAuthentication(Request $request)
{
if ($this->options['post_only'] && 'post' !== strtolower($request->getMethod())) {
if (null !== $this->logger) {
$this->logger->debug(sprintf('Authentication method not supported: %s.', $request->getMethod()));
}

return null;
}

if (null !== $this->csrfProvider) {
$csrfToken = $request->get($this->options['csrf_parameter'], null, true);

if (false === $this->csrfProvider->isCsrfTokenValid($this->options['intention'], $csrfToken)) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
}

// check here the captcha value
$userCaptcha = $request->get($this->options['captcha'], null, true);
$dummy = $request->getSession()->get('gcb_captcha');
$sessionCaptcha = $dummy['phrase'];
// if captcha is not correct, throw exception
if ($userCaptcha !== $sessionCaptcha) {
throw new BadCredentialsException('Captcha is invalid');
}

$username = trim($request->get($this->options['username_parameter'], null, true));
$password = $request->get($this->options['password_parameter'], null, true);

$request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username);

return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
}
Теперь у меня есть капча на экране входа в систему.
Играть с кодом Symfony — не лучший способ, я знаю. Если я найду какой-нибудь способ переопределить и вызвать свою собственную функцию, я опубликую его.

ЕЩЁ ПОЛЕЗНЫЙ ОТВЕТ

Я нашел еще один ответ, который может быть полезен
[link]Существует ли какое-либо событие «предварительного входа» или подобное?

Следуя этому решению, Я просто переопределил класс UsernamePasswordFormAuthenticationListener и переопределил параметр прослушивателя безопасности security.authentication.listener.form.class. Вот код:

Код: Выделить всё

namespace TCAT\StaffBundle\Listener;

use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener as BaseListener; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Log\LoggerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; use Symfony\Component\Security\Core\SecurityContextInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException;

class StaffLoginFormListener extends BaseListener
{
private $csrfProvider;

/**
* {@inheritdoc}
*/
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options
= array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfProviderInterface $csrfProvider = null)
{
parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array(
'username_parameter' => '_username',
'password_parameter' => '_password',
'csrf_parameter'     => '_csrf_token',
'captcha'           => 'captcha',
'intention'          => 'authenticate',
'post_only'          => true,
), $options), $logger, $dispatcher);

$this->csrfProvider = $csrfProvider;
}

/**
* {@inheritdoc}
*/
protected function attemptAuthentication(Request $request)
{
if ($this->options['post_only'] && 'post' !== strtolower($request->getMethod())) {
if (null !== $this->logger) {
$this->logger->debug(sprintf('Authentication method not supported: %s.', $request->getMethod()));
}

return null;
}

if (null !== $this->csrfProvider) {
$csrfToken = $request->get($this->options['csrf_parameter'], null, true);

if (false === $this->csrfProvider->isCsrfTokenValid($this->options['intention'], $csrfToken)) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
}

// throw new BadCredentialsException('Bad credentials');
$userCaptcha = $request->get($this->options['captcha'], null, true);
$dummy = $request->getSession()->get('gcb_captcha');
$sessionCaptcha = $dummy['phrase'];

if ($userCaptcha !== $sessionCaptcha) {
throw new BadCredentialsException('Captcha is invalid');
}

$username = trim($request->get($this->options['username_parameter'], null, true));
$password = $request->get($this->options['password_parameter'], null, true);

$request->getSession()->set(SecurityContextInterface::LAST_USERNAME, $username);

return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
}

}
и добавьте строку security.authentication.listener.form.class: TCAT\StaffBundle\Listener\StaffLoginFormListener в файл app/config/paramaters.yml
Кстати, я могу проверить значение своей капчи. Надеюсь, у вас все получится.

Подробнее здесь: https://stackoverflow.com/questions/147 ... login-page
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»