前書き
私は、ユーザー名の値によって管理されるパスワードのリセットフォームを作成する方法を見つけようとしています。
エラー
Path Message Invalid value Violation
data.email This value should not be blank. null
ConstraintViolation {#945 ▼
-message: "This value should not be blank."
-messageTemplate: "This value should not be blank."
-parameters: [▶]
-plural: null
-root: Form {#620 ▶}
-propertyPath: "data.email"
-invalidValue: null
-constraint: NotBlank {#477 …}
-code: "c1051bb4-d103-4f74-8988-acbcafc7fdc3"
-cause: null
}
期待されるもの
ユーザーオブジェクトを新しいパスワードで更新します。
私のコード
ForgotController.php
これはおそらくパスワードを取得する正しい方法ではないことを知っていますが、Symfony 4の忘れられたパスワードフォームを検索すると、私のバージョンに関係のないsymfony2.4の投稿が表示されます
<?php
namespace App\Controller\User;
use App\Entity\User;
use App\Form\User\ChangePasswordType;
use App\Repository\UserRepository;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class ForgotController extends Controller
{
public function forgot(Request $request, UserPasswordEncoderInterface $encoder)
{
$entityManager = $this->getDoctrine()->getManager();
$changePassword = $request->request->get('change_password');
$username = $changePassword['username'];
$password = $changePassword['plainPassword']['first'];
$user = $entityManager->getRepository(User::class)->findBy(['username' => $username]);
$userEntity = new User();
if (!$user) {
$this->addFlash('danger', 'User not found for '. $username);
}
$form = $this->createForm(ChangePasswordType::class, $userEntity);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$pass = $encoder->encodePassword($userEntity, $password);
$userEntity->setPassword($pass);
$entityManager->flush();
$this->addFlash('success', 'Password Changed!');
} catch (Exception $e) {
$this->addFlash('danger', 'Something went skew-if. Please try again.');
}
return $this->redirectToRoute('login');
}
return $this->render('user/forgot.html.twig', array('form' => $form->createView()));
}
}
ChangePasswordType.php
<?php
namespace App\Form\User;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ChangePasswordType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('username', TextType::class)
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array('label' => 'New Password'),
'second_options' => array('label' => 'Repeat New Password')
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class
));
}
}
forgot.html.twig
{% include 'builder/header.html.twig' %}
<div class="user-container" id="user-content">
{% block body %}
{% include 'builder/notices.html.twig' %}
<div class="user-container">
<i class="fas fa-user-edit fa-5x"></i>
</div>
<hr />
{{ form_start(form) }}
{{ form_row(form.username, { 'attr': {'class': 'form-control'} }) }}
{{ form_row(form.plainPassword.first, { 'attr': {'class': 'form-control'} }) }}
{{ form_row(form.plainPassword.second, { 'attr': {'class': 'form-control'} }) }}
<div class="register-btn-container">
<button class="btn btn-danger" id="return-to-dash-btn" type="button">Cancel!</button>
<button class="btn btn-primary" type="submit">Update!</button>
</div>
{{ form_end(form) }}
{% endblock %}
</div>
{% include 'builder/footer.html.twig' %}
データベースに新しいユーザーを挿入しようとしていない限り、電子メールが言及されている理由はわかりませんが、コントローラーに基づいてそれをしようとしてはいけませんか?ユーザー名で識別されるパスワードを忘れた場合のフォームを追加するにはどうすればよいですか?
回答 2 件
以下の行に沿って何かを実装します-テンプレートやルーティングのような部分を残しました。これはあなたを助けるためだけです。
フォーム1:ForgottenUserType -ユーザー名/メールのみを入力して送信
public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add("username", null, array( "label" => "Email", "attr" => array( "class" => "form-control", "id" => "basic-url", "placeholder" => "Email address for your account" ), "constraints" => array( new Email(array("message" => "Invalid Email")) ) )); }
フォーム2:ChangePasswordFormType -ユーザーが新しいパスワードを入力して繰り返します。
public function buildForm(FormBuilderInterface $builder, array $options) { parent::buildForm($builder, $options); $builder ->add('plainPassword', RepeatedType::class, array( 'type' => PasswordType::class, 'required' => false, 'first_options' => array('label' => 'New password'), 'second_options' => array('label' => 'Confirm new password'), 'invalid_message' => 'The password fields must match.', )) ; }
コントローラー:ResetPasswordController -フォーム1のユーザールックアップリクエストとフォーム2のパスワードリセットリクエストを処理します。
<?php namespace App\Controller\User; use App\Entity\User; use App\Form\User\ChangePasswordType; use App\Repository\UserRepository; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; class ResetPasswordController extends Controller { /** * Action for when a user has forgotten their password, to request ForgottenUser form * * @param Request $request */ public function requestAction(Request $request) { $tmpUser = new User(); $entityManager = $this->getDoctrine()->getManager(); $form = $this->createForm(ForgottenUserType::class, $tmpUser); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $user = $entityManager->getRepository(User::class)->findBy(['username' => $tmpUser->getUsername()]); if ($user) { //check and set token if (null === $user->getConfirmationToken()) { /** @var $tokenGenerator TokenGeneratorInterface */ $token = md5(uniqid($user->getUsername(), true)); //some unique token (you can create a nicer token generator in standalone class with a service) $user->setConfirmationToken($token); $user->setPasswordRequestedAt(new \DateTime()); $em->persist($user); $em->flush();) $this->addFlash('Info', 'If user is found, you will receive an email with further instructions.'); //send email using swiftmailer & include url with token } } else { //return to requestAction. } } //request template contains the ForgottenUserType form return $this->render(":path/to/template:request.html.twig", array( "forgotten_form" => $form->createView() )); } /** * Reset user password. * * @param Request $request * @param $token */ public function resetAction(Request $request, $token) { $entityManager = $this->getDoctrine()->getManager(); $user = $entityManager->getRepository(User::class)->findBy(['confirmationToken' => $token]); if (null === $user) { return new RedirectResponse($this->generateUrl('resetting_request')); //to requestAction above. / create route } $form = $this->createForm(ChangePasswordFormType::class, $user); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $user->SetConfirmationToken(null); $user->setPasswordRequestedAt(null); $entityManager->persist($user); $entityManager->flush() $this->addFlash("success", "Your password has been reset, log in now."); $url = $this->generateUrl('app.login'); //route to login page $response = new RedirectResponse($url); return $response; } //reset template contains the ChangePasswordFormType form return $this->render(':path/to/forgottenpasswordtemplate:reset.html.twig', array( 'token' => $token, 'form' => $form->createView(), )); } }
関連記事
- Ubuntu 1604のvsftpdでユーザー名を追加したりパスワードを変更したりするにはどうすればよいですか?
- メールとパスワードの検証がJavaScriptコードで機能しない
- Django:管理インターフェース:ユーザーパスワードを変更する方法
- AndroidのFirebaseでパスワードを変更中にアプリケーションがクラッシュしました
- トークンを送信してパスワードをリセットするためのURLをメールで送信[LaravelPassport]
- ユーザー名によってプログラムでユーザーパスワードを変更
- ユーザー名とパスワードの要素IDが一定でない場合に、サイトへのログイン要求を使用する
- usernameとuseremailの変更が機能しなかった場合、どうすればgitユーザーパスワードを変更できますか?
- Laravel 7で「メールを確認する必要があります」パスのリダイレクトを変更しますか?
- Active Directory:ユーザーは次回ログイン時にパスワードを変更する必要があります
関連した質問
- 複数のSymfonyインスタンス間でアプリケーションキャッシュを共有する方法(共有キャッシュプール)?
- symfonyメーラーの生のコンテンツがおかしい
- sylius shopapiプラグインでのユーザー登録を上書きする方法
- PHPUnitはテストを見つけられません:symfony 518
- loginformauthenticator - : getuser() "メソッドはuserinterfaceを返す必要があります
- symfony 5:本番環境の1行目で「php:// input」によってヘッダーがすでに送信されているため、セッションの開始に失敗しました
- Symfony:UploadedFileguessClientExtension()とguessExtension()をいつ使用するか?
- symfony 51:認識されないフィールド:activation_token
- symfony5のchoicEntityでのリスト表示
- ネガティブルックアラウンドで定義されたルートは、ネガティブアサーションにもかかわらずルートと一致します
パスワード変更フォームには2つのフィールドしか必要ないため、ユーザーエンティティの代わりに配列を使用します。 ChangePasswordTypeを少し調整する必要があります。
動作を忘れたアクションは次のとおりです。
UserRepositoryが注入され、すべての教義上のナンセンスが取り除かれます。ここで1つ注意すべき点があります。
userInfo配列を作成し、フォーム処理に任せます。必要がない場合は、リクエストオブジェクトから属性を直接取得することに煩わされたくありません。
次に、実際のユーザーエンティティを取得して更新します。 findByの代わりにfindOneByを使用していることに注意してください。ユーザー名が有効であることを確認します。本当に空想を得たい場合は、フォームに検証制約を追加して、このチェックを自動的に行うことができます。
私はすべてのtry/catchのものを取り除きました。コードが乱雑になります。この時点までに例外がスローされた場合、それは本当に例外的であり、デフォルトの例外ハンドラーで処理できます。
パスワードエンコーダーはまさにぴったりです。
そして、$entityManager->の代わりに flush()$userRepository->を使用しました 流す();すぐに使用できるリポジトリにはフラッシュメソッドがないため、追加する必要があります。
個人的には、エンティティマネージャではなくリポジトリだけを扱うのが好きです。しかし、必要に応じて、戻ってリポジトリの代わりにマネージャーを挿入することができます。あなたの電話。
また、コメントで述べたように、ユーザーが他のユーザーのパスワードを変更できないようにセキュリティを追加する必要があります。