FOSUserBundle - 更改默认配置,覆盖一些默认设置
FOSUserBundle - changes in default configuration, overriding some default settings
我是 Symfony 2 的新手。我必须在 Symfony 2 中构建一个应用程序(我使用的是 2.8 和最新版本的 FOSUser Bundle)。大部分工作已完成,但我必须对默认安全设置进行一些更改。我找了他们两天,但我对如何解决这个问题一无所知。假定的更改如下:
- 注册 - 我启用了电子邮件确认功能,但我不知道如何确认 link 一小时后过期 and/or 使用一次(单击)。 config.yaml setting ttl 中有设置,但仅用于重设密码。
- 注册 - 在确认用户被阻止登录之前,存在 Symfony 2 异常 - 禁用帐户工作,呈现有关它的短消息。实际上我必须将重定向设置到另一个页面(我想是模板)以呈现 'this account is blocked...' 和 link 的自定义消息以发送另一个带有确认令牌的 link (我说得对吗? link 在电子邮件中是确认令牌?)。
- RESETTING - 如前所述,link(令牌?)的 ttl 重置密码设置为一小时,但我不知道如何使其在使用一次(单击)后过期。
我知道如何覆盖 FOSUser 的某些模板,但我不清楚应该覆盖哪些文件来更改这些内容。
我注意到我的 FOSUser 使用 Symfony 2 Exceptions 文件,如果我更改了我的 Exception 文件中的消息内容,它也会在我的页面上更改,但我不知道如何让它变得更好并覆盖它,添加所有必要的功能。
我试图使用 Compiler Pass (http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html) 覆盖 AuthenticationListener(来自 FOSUser),但我不知道它是否有效,因为覆盖的 Listener 中的任何更改都不可见。其实我不知道这是否是我应该覆盖的文件。
我已经检查了一些 Whosebug 问题,但我还没有找到答案。
FOSUser Bundle - Prevent Disabled users from logging in
这对我不起作用,因为用户被阻止了,我只需要覆盖异常消息并使用另一个 link 发送确认消息创建重定向。
FOS user bundle authentication
我已经尝试实施此处指出的解决方案,但它没有用,我不确定我是否真的需要这么复杂的解决方案。
提前感谢您的帮助,我有人需要看我的文件,只需编写配置,我会 post 这里有必要的。
我终于想通了所有这些事情。如果有人有类似的问题,我建议阅读 Symfony 文档中的这些主题:
Overriding FOSUser B controllers
Hooking into a controller
事实证明,对于所描述的功能,我需要覆盖 FOSUser Bundle 中的一些文件,有时 Controller 就足够了,有时我需要修改 EventListener(实际上我什至创建了自己的事件)。有不止一种方法。
最难的部分是一键 link 重置密码。我使用了一个标志,在发送电子邮件时设置为 false,在单击 link 时设置为 true 以防止再次使用 link。问题是,Resetting Controller 是 'executed' 两次,因此在单击提交时出现重定向,因为标志为 true。我在会话中添加了一些计数,以便在您点击提交按钮时省略检查标志的代码部分(重置控制器中重置方法的第二次使用),但它只阻止了第二次点击提交,所以实际上link不能用两次,但是可以看到两次form,这不是我想要达到的效果,但总比没有好。如果有人知道如何升级它,我将不胜感激
<?php
namespace My\UserBundle\Controller;
use FOS\UserBundle\Controller\ResettingController as FOSResettingController;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use My\UserBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use My\UserBundle\UserEvents;
/**
* Controller managing the resetting of the password
*
* @author Thibault Duplessis <thibault.duplessis@gmail.com>
* @author Christophe Coevoet <stof@notk.org>
*/
class ResettingController extends FOSResettingController
{
/**
* Request reset user password: submit form and send email
*/
public function sendEmailAction(Request $request)
{
$username = $request->request->get('username');
/** @var $user UserInterface */
$user = $this->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);
if (null === $user) {
return $this->render('FOSUserBundle:Resetting:request.html.twig', array(
'invalid_username' => $username
));
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
return $this->render('FOSUserBundle:Resetting:passwordAlreadyRequested.html.twig');
}
if (null === $user->getConfirmationToken()) {
/** @var $tokenGenerator \FOS\UserBundle\Util\TokenGeneratorInterface */
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$user->setPasswordRequestedClicked(false);
$this->get('fos_user.user_manager')->updateUser($user);
$_SESSION['views'] = 1;
return new RedirectResponse($this->generateUrl('fos_user_resetting_check_email',
array('email' => $this->getObfuscatedEmail($user))
));
}
/**
* Reset user password
*/
public function resetAction(Request $request, $token)
{
/** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.resetting.form.factory');
/** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->findUserByConfirmationToken($token);
//Here there is a reaction for using expired token (column confirmation token === null) - redirection to page with possibility of sending another one.
if (null === $user) {
return $this->redirectToRoute('fos_user_invalid_token_click');
}
if ($_SESSION['views'] == 1){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
} else {
$user->setPasswordRequestedClicked(true);
$userManager->updateUser($user);
$_SESSION['views']++;
$_SESSION['views']++;
}
} else {
$_SESSION['views']++;
}
if ($_SESSION['views'] == 5){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
}
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_profile_show');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$userManager->updateUser($user);
return $this->render('FOSUserBundle:Resetting:reset.html.twig', array(
'token' => $token,
'form' => $form->createView(),
));
}
public function InvalidTokenTtlMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenTtlRes.html.twig');
}
public function InvalidTokenClickMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenClickRes.html.twig');
}
}
我的听众:
<?php
namespace My\UserBundle\EventListener;
use FOS\UserBundle\EventListener\ResettingListener as FOSResettingListener;
use FOS\UserBundle\FOSUserEvents;
use My\UserBundle\UserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use My\UserBundle\Entity\User;
class ResettingListener extends FOSResettingListener
{
private $router;
private $tokenTtl;
public function __construct(UrlGeneratorInterface $router, $tokenTtl)
{
$this->router = $router;
$this->tokenTtl = $tokenTtl;
}
public static function getSubscribedEvents()
{
return array(
UserEvents::RESETTING_RESET_CLICK_CHECK => 'onResettingClickCheck',
FOSUserEvents::RESETTING_RESET_INITIALIZE => 'onResettingResetInitialize',
FOSUserEvents::RESETTING_RESET_SUCCESS => 'onResettingResetSuccess',
);
}
public function onResettingClickCheck(GetResponseUserEvent $event){
//checking if link hasn't expired due to its usage
if ($event->getUser()->isPasswordRequestedClicked() === true){
$event->setResponse(new RedirectResponse($this->router->generate('fos_user_invalid_token_click')));
}
}
public function onResettingResetInitialize(GetResponseUserEvent $event)
{
//checking if link hasn't expired due to exceeding token Ttl
if (!$event->getUser()->isPasswordRequestNonExpired($this->tokenTtl)) {
$event->setResponse(new RedirectResponse($this->router->generate('fos_user_invalid_token_ttl')));
}
}
public function onResettingResetSuccess(FormEvent $event)
{
/** @var $user \FOS\UserBundle\Model\UserInterface */
$user = $event->getForm()->getData();
$user->setConfirmationToken(null);
$user->setPasswordRequestedAt(null);
$user->setEnabled(true);
}
}
和我的用户实体:
<?php
namespace My\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use My\BackendBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="My\UserBundle\Repository\UserRepository")
*/
class User extends BaseUser
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable = false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Gedmo\Slug(fields={"username"})
* @ORM\Column(length=128, unique=true)
*/
private $slug;
/**
*
* @ORM\ManyToMany(targetEntity="\My\BackendBundle\Entity\Event", mappedBy="users")
* @ORM\JoinColumn(name="id", referencedColumnName="id", nullable=false)
* @ORM\OrderBy({"date"="ASC"})
*
*/
protected $events;
/**
* @var \Doctrine\Common\Collections\ArrayCollection $event_org
* @ORM\OneToMany(targetEntity="\My\BackendBundle\Entity\Event", mappedBy="user_org", cascade={"all"})
*/
protected $event_org;
/**
* @var \DateTime
* @ORM\Column(name="confirmation_token_requested_at", type="datetime")
*/
protected $confirmationTokenRequestedAt;
/**
* @var boolean
* @ORM\Column(name="password_requested_clicked", type="boolean", nullable=true)
*/
protected $passwordRequestedClicked;
public function __toString()
{
return $this->getUsername();
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
public function __construct()
{
parent::__construct();
$this->event_org = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add event
*
* @param \My\BackendBundle\Entity\Event $event
*
* @return User
*/
public function addEvent(\My\BackendBundle\Entity\Event $event)
{
$this->events[] = $event;
$event->addUser($this);
return $this;
}
/**
* Remove event
*
* @param \My\BackendBundle\Entity\Event $event
*/
public function removeEvent(\My\BackendBundle\Entity\Event $event)
{
$this->events->removeElement($event);
}
/**
* Get events
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getEvents()
{
return $this->events;
}
/**
* Set slug
*
* @param string $slug
*
* @return User
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* @return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Add eventOrg
*
* @param \My\BackendBundle\Entity\Event $eventOrg
*
* @return User
*/
public function addEventOrg(\My\BackendBundle\Entity\Event $eventOrg)
{
$this->event_org[] = $eventOrg;
return $this;
}
/**
* Remove eventOrg
*
* @param \My\BackendBundle\Entity\Event $eventOrg
*/
public function removeEventOrg(\My\BackendBundle\Entity\Event $eventOrg)
{
$this->event_org->removeElement($eventOrg);
}
/**
* Get eventOrg
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getEventOrg()
{
return $this->event_org;
}
/**
* Set confirmationTokenRequestedAt
*
* @param \DateTime $confirmationTokenRequestedAt
*
* @return User
*/
public function setConfirmationTokenRequestedAt(\DateTime $date = null)
{
$this->confirmationTokenRequestedAt = $date;
return $this;
}
/**
* Gets the timestamp that the user requested a confirmation_token.
*
* @return null|\DateTime
*/
public function getConfirmationTokenRequestedAt()
{
return $this->confirmationTokenRequestedAt;
}
public function isConfirmationTokenNonExpired($ttl)
{
return $this->getConfirmationTokenRequestedAt() instanceof \DateTime &&
$this->getConfirmationTokenRequestedAt()->getTimestamp() + $ttl > time();
}
/**
* Set passwordRequestedClicked
*
* @param boolean $passwordRequestedClicked
*
* @return User
*/
public function setPasswordRequestedClicked($boolean)
{
$this->passwordRequestedClicked = (Boolean) $boolean;
return $this;
}
/**
* Get passwordRequestedClicked
*
* @return boolean
*/
public function getPasswordRequestedClicked()
{
return $this->passwordRequestedClicked;
}
/**
* Checks whether the user has used password request.
*
*
* @return Boolean true if the user is enabled, false otherwise
*/
public function isPasswordRequestedClicked() {
return $this->passwordRequestedClicked;
}
}
如果有人想获取剩余问题的代码,请给我留言,我会在这里提供:)。
重置控制器:
<?php
namespace My\UserBundle\Controller;
use FOS\UserBundle\Controller\ResettingController as FOSResettingController;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use My\UserBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use My\UserBundle\UserEvents;
class ResettingController extends FOSResettingController
{
public function sendEmailAction(Request $request)
{
$username = $request->request->get('username');
$user = $this->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);
if (null === $user) {
return $this->render('FOSUserBundle:Resetting:request.html.twig', array(
'invalid_username' => $username
));
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
return $this->render('FOSUserBundle:Resetting:passwordAlreadyRequested.html.twig');
}
if (null === $user->getConfirmationToken()) {
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$user->setPasswordRequestedClicked(false);
$this->get('fos_user.user_manager')->updateUser($user);
$_SESSION['views'] = 1;
return new RedirectResponse($this->generateUrl('fos_user_resetting_check_email',
array('email' => $this->getObfuscatedEmail($user))
));
}
public function resetAction(Request $request, $token)
{
$formFactory = $this->get('fos_user.resetting.form.factory');
$userManager = $this->get('fos_user.user_manager');
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->findUserByConfirmationToken($token);
//Here there is a reaction for using expired token (column confirmation token === null) - redirection to page with possibility of sending another one.
if (null === $user) {
return $this->redirectToRoute('fos_user_invalid_token_click');
}
if ($_SESSION['views'] == 1){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
} else {
$user->setPasswordRequestedClicked(true);
$userManager->updateUser($user);
$_SESSION['views']++;
$_SESSION['views']++;
}
} else {
$_SESSION['views']++;
}
if ($_SESSION['views'] == 5){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
}
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_profile_show');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$userManager->updateUser($user);
return $this->render('FOSUserBundle:Resetting:reset.html.twig', array(
'token' => $token,
'form' => $form->createView(),
));
}
public function InvalidTokenTtlMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenTtlRes.html.twig');
}
public function InvalidTokenClickMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenClickRes.html.twig');
}
}
我是 Symfony 2 的新手。我必须在 Symfony 2 中构建一个应用程序(我使用的是 2.8 和最新版本的 FOSUser Bundle)。大部分工作已完成,但我必须对默认安全设置进行一些更改。我找了他们两天,但我对如何解决这个问题一无所知。假定的更改如下:
- 注册 - 我启用了电子邮件确认功能,但我不知道如何确认 link 一小时后过期 and/or 使用一次(单击)。 config.yaml setting ttl 中有设置,但仅用于重设密码。
- 注册 - 在确认用户被阻止登录之前,存在 Symfony 2 异常 - 禁用帐户工作,呈现有关它的短消息。实际上我必须将重定向设置到另一个页面(我想是模板)以呈现 'this account is blocked...' 和 link 的自定义消息以发送另一个带有确认令牌的 link (我说得对吗? link 在电子邮件中是确认令牌?)。
- RESETTING - 如前所述,link(令牌?)的 ttl 重置密码设置为一小时,但我不知道如何使其在使用一次(单击)后过期。
我知道如何覆盖 FOSUser 的某些模板,但我不清楚应该覆盖哪些文件来更改这些内容。
我注意到我的 FOSUser 使用 Symfony 2 Exceptions 文件,如果我更改了我的 Exception 文件中的消息内容,它也会在我的页面上更改,但我不知道如何让它变得更好并覆盖它,添加所有必要的功能。
我试图使用 Compiler Pass (http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html) 覆盖 AuthenticationListener(来自 FOSUser),但我不知道它是否有效,因为覆盖的 Listener 中的任何更改都不可见。其实我不知道这是否是我应该覆盖的文件。
我已经检查了一些 Whosebug 问题,但我还没有找到答案。
FOSUser Bundle - Prevent Disabled users from logging in 这对我不起作用,因为用户被阻止了,我只需要覆盖异常消息并使用另一个 link 发送确认消息创建重定向。
FOS user bundle authentication 我已经尝试实施此处指出的解决方案,但它没有用,我不确定我是否真的需要这么复杂的解决方案。
提前感谢您的帮助,我有人需要看我的文件,只需编写配置,我会 post 这里有必要的。
我终于想通了所有这些事情。如果有人有类似的问题,我建议阅读 Symfony 文档中的这些主题: Overriding FOSUser B controllers Hooking into a controller
事实证明,对于所描述的功能,我需要覆盖 FOSUser Bundle 中的一些文件,有时 Controller 就足够了,有时我需要修改 EventListener(实际上我什至创建了自己的事件)。有不止一种方法。
最难的部分是一键 link 重置密码。我使用了一个标志,在发送电子邮件时设置为 false,在单击 link 时设置为 true 以防止再次使用 link。问题是,Resetting Controller 是 'executed' 两次,因此在单击提交时出现重定向,因为标志为 true。我在会话中添加了一些计数,以便在您点击提交按钮时省略检查标志的代码部分(重置控制器中重置方法的第二次使用),但它只阻止了第二次点击提交,所以实际上link不能用两次,但是可以看到两次form,这不是我想要达到的效果,但总比没有好。如果有人知道如何升级它,我将不胜感激
<?php
namespace My\UserBundle\Controller;
use FOS\UserBundle\Controller\ResettingController as FOSResettingController;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use My\UserBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use My\UserBundle\UserEvents;
/**
* Controller managing the resetting of the password
*
* @author Thibault Duplessis <thibault.duplessis@gmail.com>
* @author Christophe Coevoet <stof@notk.org>
*/
class ResettingController extends FOSResettingController
{
/**
* Request reset user password: submit form and send email
*/
public function sendEmailAction(Request $request)
{
$username = $request->request->get('username');
/** @var $user UserInterface */
$user = $this->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);
if (null === $user) {
return $this->render('FOSUserBundle:Resetting:request.html.twig', array(
'invalid_username' => $username
));
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
return $this->render('FOSUserBundle:Resetting:passwordAlreadyRequested.html.twig');
}
if (null === $user->getConfirmationToken()) {
/** @var $tokenGenerator \FOS\UserBundle\Util\TokenGeneratorInterface */
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$user->setPasswordRequestedClicked(false);
$this->get('fos_user.user_manager')->updateUser($user);
$_SESSION['views'] = 1;
return new RedirectResponse($this->generateUrl('fos_user_resetting_check_email',
array('email' => $this->getObfuscatedEmail($user))
));
}
/**
* Reset user password
*/
public function resetAction(Request $request, $token)
{
/** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.resetting.form.factory');
/** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->findUserByConfirmationToken($token);
//Here there is a reaction for using expired token (column confirmation token === null) - redirection to page with possibility of sending another one.
if (null === $user) {
return $this->redirectToRoute('fos_user_invalid_token_click');
}
if ($_SESSION['views'] == 1){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
} else {
$user->setPasswordRequestedClicked(true);
$userManager->updateUser($user);
$_SESSION['views']++;
$_SESSION['views']++;
}
} else {
$_SESSION['views']++;
}
if ($_SESSION['views'] == 5){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
}
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_profile_show');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$userManager->updateUser($user);
return $this->render('FOSUserBundle:Resetting:reset.html.twig', array(
'token' => $token,
'form' => $form->createView(),
));
}
public function InvalidTokenTtlMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenTtlRes.html.twig');
}
public function InvalidTokenClickMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenClickRes.html.twig');
}
}
我的听众:
<?php
namespace My\UserBundle\EventListener;
use FOS\UserBundle\EventListener\ResettingListener as FOSResettingListener;
use FOS\UserBundle\FOSUserEvents;
use My\UserBundle\UserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use My\UserBundle\Entity\User;
class ResettingListener extends FOSResettingListener
{
private $router;
private $tokenTtl;
public function __construct(UrlGeneratorInterface $router, $tokenTtl)
{
$this->router = $router;
$this->tokenTtl = $tokenTtl;
}
public static function getSubscribedEvents()
{
return array(
UserEvents::RESETTING_RESET_CLICK_CHECK => 'onResettingClickCheck',
FOSUserEvents::RESETTING_RESET_INITIALIZE => 'onResettingResetInitialize',
FOSUserEvents::RESETTING_RESET_SUCCESS => 'onResettingResetSuccess',
);
}
public function onResettingClickCheck(GetResponseUserEvent $event){
//checking if link hasn't expired due to its usage
if ($event->getUser()->isPasswordRequestedClicked() === true){
$event->setResponse(new RedirectResponse($this->router->generate('fos_user_invalid_token_click')));
}
}
public function onResettingResetInitialize(GetResponseUserEvent $event)
{
//checking if link hasn't expired due to exceeding token Ttl
if (!$event->getUser()->isPasswordRequestNonExpired($this->tokenTtl)) {
$event->setResponse(new RedirectResponse($this->router->generate('fos_user_invalid_token_ttl')));
}
}
public function onResettingResetSuccess(FormEvent $event)
{
/** @var $user \FOS\UserBundle\Model\UserInterface */
$user = $event->getForm()->getData();
$user->setConfirmationToken(null);
$user->setPasswordRequestedAt(null);
$user->setEnabled(true);
}
}
和我的用户实体:
<?php
namespace My\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use My\BackendBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="My\UserBundle\Repository\UserRepository")
*/
class User extends BaseUser
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable = false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Gedmo\Slug(fields={"username"})
* @ORM\Column(length=128, unique=true)
*/
private $slug;
/**
*
* @ORM\ManyToMany(targetEntity="\My\BackendBundle\Entity\Event", mappedBy="users")
* @ORM\JoinColumn(name="id", referencedColumnName="id", nullable=false)
* @ORM\OrderBy({"date"="ASC"})
*
*/
protected $events;
/**
* @var \Doctrine\Common\Collections\ArrayCollection $event_org
* @ORM\OneToMany(targetEntity="\My\BackendBundle\Entity\Event", mappedBy="user_org", cascade={"all"})
*/
protected $event_org;
/**
* @var \DateTime
* @ORM\Column(name="confirmation_token_requested_at", type="datetime")
*/
protected $confirmationTokenRequestedAt;
/**
* @var boolean
* @ORM\Column(name="password_requested_clicked", type="boolean", nullable=true)
*/
protected $passwordRequestedClicked;
public function __toString()
{
return $this->getUsername();
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
public function __construct()
{
parent::__construct();
$this->event_org = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add event
*
* @param \My\BackendBundle\Entity\Event $event
*
* @return User
*/
public function addEvent(\My\BackendBundle\Entity\Event $event)
{
$this->events[] = $event;
$event->addUser($this);
return $this;
}
/**
* Remove event
*
* @param \My\BackendBundle\Entity\Event $event
*/
public function removeEvent(\My\BackendBundle\Entity\Event $event)
{
$this->events->removeElement($event);
}
/**
* Get events
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getEvents()
{
return $this->events;
}
/**
* Set slug
*
* @param string $slug
*
* @return User
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* @return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* Add eventOrg
*
* @param \My\BackendBundle\Entity\Event $eventOrg
*
* @return User
*/
public function addEventOrg(\My\BackendBundle\Entity\Event $eventOrg)
{
$this->event_org[] = $eventOrg;
return $this;
}
/**
* Remove eventOrg
*
* @param \My\BackendBundle\Entity\Event $eventOrg
*/
public function removeEventOrg(\My\BackendBundle\Entity\Event $eventOrg)
{
$this->event_org->removeElement($eventOrg);
}
/**
* Get eventOrg
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getEventOrg()
{
return $this->event_org;
}
/**
* Set confirmationTokenRequestedAt
*
* @param \DateTime $confirmationTokenRequestedAt
*
* @return User
*/
public function setConfirmationTokenRequestedAt(\DateTime $date = null)
{
$this->confirmationTokenRequestedAt = $date;
return $this;
}
/**
* Gets the timestamp that the user requested a confirmation_token.
*
* @return null|\DateTime
*/
public function getConfirmationTokenRequestedAt()
{
return $this->confirmationTokenRequestedAt;
}
public function isConfirmationTokenNonExpired($ttl)
{
return $this->getConfirmationTokenRequestedAt() instanceof \DateTime &&
$this->getConfirmationTokenRequestedAt()->getTimestamp() + $ttl > time();
}
/**
* Set passwordRequestedClicked
*
* @param boolean $passwordRequestedClicked
*
* @return User
*/
public function setPasswordRequestedClicked($boolean)
{
$this->passwordRequestedClicked = (Boolean) $boolean;
return $this;
}
/**
* Get passwordRequestedClicked
*
* @return boolean
*/
public function getPasswordRequestedClicked()
{
return $this->passwordRequestedClicked;
}
/**
* Checks whether the user has used password request.
*
*
* @return Boolean true if the user is enabled, false otherwise
*/
public function isPasswordRequestedClicked() {
return $this->passwordRequestedClicked;
}
}
如果有人想获取剩余问题的代码,请给我留言,我会在这里提供:)。
重置控制器:
<?php
namespace My\UserBundle\Controller;
use FOS\UserBundle\Controller\ResettingController as FOSResettingController;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use My\UserBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use My\UserBundle\UserEvents;
class ResettingController extends FOSResettingController
{
public function sendEmailAction(Request $request)
{
$username = $request->request->get('username');
$user = $this->get('fos_user.user_manager')->findUserByUsernameOrEmail($username);
if (null === $user) {
return $this->render('FOSUserBundle:Resetting:request.html.twig', array(
'invalid_username' => $username
));
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
return $this->render('FOSUserBundle:Resetting:passwordAlreadyRequested.html.twig');
}
if (null === $user->getConfirmationToken()) {
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$user->setPasswordRequestedClicked(false);
$this->get('fos_user.user_manager')->updateUser($user);
$_SESSION['views'] = 1;
return new RedirectResponse($this->generateUrl('fos_user_resetting_check_email',
array('email' => $this->getObfuscatedEmail($user))
));
}
public function resetAction(Request $request, $token)
{
$formFactory = $this->get('fos_user.resetting.form.factory');
$userManager = $this->get('fos_user.user_manager');
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->findUserByConfirmationToken($token);
//Here there is a reaction for using expired token (column confirmation token === null) - redirection to page with possibility of sending another one.
if (null === $user) {
return $this->redirectToRoute('fos_user_invalid_token_click');
}
if ($_SESSION['views'] == 1){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
} else {
$user->setPasswordRequestedClicked(true);
$userManager->updateUser($user);
$_SESSION['views']++;
$_SESSION['views']++;
}
} else {
$_SESSION['views']++;
}
if ($_SESSION['views'] == 5){
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(UserEvents::RESETTING_RESET_CLICK_CHECK, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
}
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_profile_show');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::RESETTING_RESET_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$userManager->updateUser($user);
return $this->render('FOSUserBundle:Resetting:reset.html.twig', array(
'token' => $token,
'form' => $form->createView(),
));
}
public function InvalidTokenTtlMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenTtlRes.html.twig');
}
public function InvalidTokenClickMessageAction() {
return $this->render('UserBundle:Resetting:invalidTokenClickRes.html.twig');
}
}