5.2のバージョンの下でSymfonyのログイン試み
Symfony 5.2機能は、複数のログインの試みに対して当社のウェブサイトをセキュリティー保護することができます.
これがdocs => Login Throttlingです
しかし、古いバージョンでそれを行うには?これが私が次にあなたに見せるつもりです.
プロジェクト
このプロジェクトについては、ブログを作成しましょう.このブログは登録ユーザーのみにアクセスできます.匿名ユーザーは' login 'と' register 'にのみアクセスできます.
レジスタページでは、悪いボットを避けるために、我々はCAPTCHAを使用するが、1つのCAPTCHAは十分です、我々はログインページのためにそれを必要としません.
プロジェクトの囲炉裏に行ってみよう.プロジェクト を作成しますは、
あなたの論理をコントローラ に書きなさい
そして今は働きましょう.
新しいエンティティを作成する
それで、我々は我々のウェブサイトに各々の接続を知っていたいです.それぞれの接続については、IPアドレス、メールを使用して日付を知りたい.
エンティティを作成します.それをlogin試みと呼び、質問に答えます.
LogInformatuenticator
あなたが
コンストラクターが2つの新しいプライベート変数を追加する前に、最初に$ ipaddressと
このクラスでは、2つのメソッドが我々を結び付けます.
getcredentials
このメソッドはすべての接続を取得します.ログとダイを試して、$ credentialsをダンプすることができます、あなたは使用されるメールにアクセスするでしょう、ハッシュされないパスワードとcsrftoken.パーフェクト!これはまさに我々が望む論理だ.
したがって、戻り値の直前にこのメソッドで、$ loglogIntryの変数を新しいlogin試み(エンティティ)に等しく追加します.パラメータのIPアドレスとメールに必要なことを忘れないでください.右、あなたの方法を見て、我々は要求へのアクセスを持っている!したがって、最初のパラメータは
私はIPアドレスのグローバル変数が欲しいので、プライベート変数
これでデータを永続化してフラッシュするだけです.ログインしてデータベースを見てみてください.
パーフェクト!
getCredentialsメソッドは次のようになります.
特徴を作る
私たちのCheckCredentialsメソッドのロジックは少し長いので、私は特徴を作成することを好む.それをSecurityLoginInstallTraitと呼んで、それを忘れないために、
我々の特性に戻って、ASパラメタでSecureのメソッドを作成し始めてください: LoginFittRepository $ repo ストリング$電子メール 文字列ipaddress EntityManagerInterface $ Manager urlgeneratorinterface $ url それから、我々はエラーメッセージで2つの試みからユーザーを防ぎたいです.4番目のトライは、最後の5番目の試みは彼のIPアドレスをブロックします.条件を書き出す
OKで、一歩一歩.
CustomUserMessageAuthenticationExceptionは自分の名前としてユーザーのカスタムメッセージエラーです.' use文'を使うのを忘れないでください
ここでLoginHiteRepositoryの中に行き、recentLoginRetryメソッドを作成しましょう.
方法
今までの3分からのメールアドレスの接続を知りたいので、書きましょう.
最後の条件を書きましょうが、その前に新しいエンティティを作成する必要があります.
最後の実体
ユーザーが3分以下で5回接続しようとするならば、彼のIPアドレスは我々のサイトでブロックされます.したがって、2つのプロパティを持つipblockエンティティを作成します. ipaddress ( string ) Blockedat ( datetimepers immutable ) すべてのセッターを削除し、
エンティティは次のようになります.
あなたの特性は次のようになります.
loginfoに戻る
checkCredentialsメソッドで作業する前に、新しいプライベートlogintry対面$ repoを作成し、コンストラクターに追加します.
では、メソッドを呼び出して安全なメソッドを呼び出します.パラメータで必要なことを思い出してください. LoginHandTrepository Eメール IPアドレス EntityManagerInterface urlgeneratorinterface それで、我々は
そして、それは、我々のロジックが行われます.ユーザーが3分またはそれの下で5回接続しようとするならば、彼のIPアドレスは我々のデータベースにあります.
最後に
我々は、当社のウェブサイトからユーザーのアクセスをブロックしたい.匿名のユーザーが'/login 'と'/register 'にのみアクセスできることを忘れないでください.それから、ログインとレジスターのコントローラに行ってください.
まず、
次に、IPアドレスがブロックされていない場合、このページにアクセスできないようにします.したがって、RegisterControllerとLoginControllerと同じパラメータを追加してください.
例えば、あなたは言うことができました:「あなたは、このウェブサイトへのアクセスを持っていません.」
そしてもちろん、あなたの連絡先ページへのアクセスをすべてのユーザーがブロックすることができます.
あなたがこの記事が好きで、あなたがどんな質問またはどんな改善でもあるならば、ちょっと私に知らせてください
乾杯!
これがdocs => Login Throttlingです
しかし、古いバージョンでそれを行うには?これが私が次にあなたに見せるつもりです.
プロジェクト
このプロジェクトについては、ブログを作成しましょう.このブログは登録ユーザーのみにアクセスできます.匿名ユーザーは' login 'と' register 'にのみアクセスできます.
レジスタページでは、悪いボットを避けるために、我々はCAPTCHAを使用するが、1つのCAPTCHAは十分です、我々はログインページのためにそれを必要としません.
プロジェクトの囲炉裏に行ってみよう.
make:user
とmake:auth
をしますそして今は働きましょう.
新しいエンティティを作成する
それで、我々は我々のウェブサイトに各々の接続を知っていたいです.それぞれの接続については、IPアドレス、メールを使用して日付を知りたい.
エンティティを作成します.それをlogin試みと呼び、質問に答えます.
New property name (press <return> to stop adding fields):
> email
Field type (enter ? to see all types) [string]:
>
Field length [255]:
>
Can this field be null in the database (nullable) (yes/no) [no]:
>
updated: src/Entity/LoginAttempt.php
Add another property? Enter the property name (or press <return> to stop adding fields):
> ipAddress
Field type (enter ? to see all types) [string]:
>
Field length [255]:
>
Can this field be null in the database (nullable) (yes/no) [no]:
>
updated: src/Entity/LoginAttempt.php
Add another property? Enter the property name (or press <return> to stop adding fields):
> date
Field type (enter ? to see all types) [string]:
> datetime_immutable
datetime_immutable
Can this field be null in the database (nullable) (yes/no) [no]:
>
右、現在エンティティを変更できます.必要に応じて変数を入力することができます.すべてのセッターを削除します、私たちはそれらを必要としません、そして、建設者をつくります.コンストラクタではstring $email
とstring $ipAddress
を使い、日付はnew DatetimeImmutable('now')
です.私は、フランスのために時間を得るために、個人的にdate_default_timezone_set('Europe/Paris')
を加えました.エンティティは次のようになります.class LoginAttempt
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/**
* @ORM\Column(type="string", length=255)
*/
private string $email;
/**
* @ORM\Column(type="string", length=255)
*/
private string $ipAddress;
/**
* @ORM\Column(type="datetime_immutable")
*/
private \DateTimeImmutable $date;
public function __construct(string $ipAddress, string $email)
{
date_default_timezone_set('Europe/Paris');
$this->ipAddress = $ipAddress;
$this->email = $email;
$this->date = new \DateTimeImmutable('now');
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function getIpAddress(): ?string
{
return $this->ipAddress;
}
public function getDate(): ?\DateTimeImmutable
{
return $this->date;
}
}
LogInformatuenticator
あなたが
make auth
をしたならば、あなたはあなたのログインのためにロジックをつくりました、私はこのクラスLogInformatuenticatorと呼ばれました.コンストラクターが2つの新しいプライベート変数を追加する前に、最初に$ ipaddressと
EntityManagerInterface $manager
と呼んで、マネージャをマネージャに追加します.後でipaddressに説明します.このクラスでは、2つのメソッドが我々を結び付けます.
public function getCredentials(Request $request)
public function checkCredentials($credentials, UserInterface $user)
getcredentials
このメソッドはすべての接続を取得します.ログとダイを試して、$ credentialsをダンプすることができます、あなたは使用されるメールにアクセスするでしょう、ハッシュされないパスワードとcsrftoken.パーフェクト!これはまさに我々が望む論理だ.
したがって、戻り値の直前にこのメソッドで、$ loglogIntryの変数を新しいlogin試み(エンティティ)に等しく追加します.パラメータのIPアドレスとメールに必要なことを忘れないでください.右、あなたの方法を見て、我々は要求へのアクセスを持っている!したがって、最初のパラメータは
$request->getClientIp()
で、2番目は資格情報です.配列として、$ credentials [ email ]を書く必要があります.私はIPアドレスのグローバル変数が欲しいので、プライベート変数
$this->ipaddress = $request->getClientIp()
を使用します.これでデータを永続化してフラッシュするだけです.ログインしてデータベースを見てみてください.
パーフェクト!
getCredentialsメソッドは次のようになります.
public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
$newLoginAttempt = new LoginAttempt($request->getClientIp(), $credentials['email']);
$this->ipAddress = $request->getClientIp();
$this->entityManager->persist($newLoginAttempt);
$this->entityManager->flush();
return $credentials;
}
特徴を作る
私たちのCheckCredentialsメソッドのロジックは少し長いので、私は特徴を作成することを好む.それをSecurityLoginInstallTraitと呼んで、それを忘れないために、
use TargetPathTrait;
の上であなたのLogInformauthicatorのクラスで直接それを使ってください!我々の特性に戻って、ASパラメタでSecureのメソッドを作成し始めてください:
if(count($repo->recentLoginAttempts($email)) === 2){
throw new CustomUserMessageAuthenticationException('3 attempts left');
}
if(count($repo->recentLoginAttempts($email)) === 3){
throw new CustomUserMessageAuthenticationException('2 attempts left');
}
if(count($repo->recentLoginAttempts($email)) === 4){
throw new CustomUserMessageAuthenticationException('Be carefull its your last attempt');
}
WOW待ちました、RecentLoginRetryメソッド、CustomUserMessageAuthenticationExceptionとは何ですか?OKで、一歩一歩.
CustomUserMessageAuthenticationExceptionは自分の名前としてユーザーのカスタムメッセージエラーです.' use文'を使うのを忘れないでください
ここでLoginHiteRepositoryの中に行き、recentLoginRetryメソッドを作成しましょう.
方法
今までの3分からのメールアドレスの接続を知りたいので、書きましょう.
class LoginAttemptRepository extends ServiceEntityRepository
{
const DELAY_IN_MINUTES = 3;
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, LoginAttempt::class);
}
public function recentLoginAttempts(string $email)
{
date_default_timezone_set('Europe/Paris');
$timeAgo = new \DateTimeImmutable(sprintf('-%d minutes', self::DELAY_IN_MINUTES));
return $this->createQueryBuilder('l')
->andWhere('l.date >= :date')
->andWhere('l.email = :email')
->setParameter('date', $timeAgo)
->setParameter('email', $email)
->getQuery()
->getResult()
;
}
現在、あなたは我々の状況を理解しなければなりません.例えば、if(count($this->repo->recentLoginAttempts($email)) === 3){
throw new CustomUserMessageAuthenticationException('2 attempts left');
}
私はすべての回をユーザーが私たちのウェブサイトにマイナス3分の間に接続しようとするとカウントされます.合計が3に等しいならば、彼は新しいカスタムメイドのメッセージを得ます.最後の条件を書きましょうが、その前に新しいエンティティを作成する必要があります.
最後の実体
ユーザーが3分以下で5回接続しようとするならば、彼のIPアドレスは我々のサイトでブロックされます.したがって、2つのプロパティを持つipblockエンティティを作成します.
string $ipAddress
でコンストラクタを作成し、プロパティのブロック化を自動化します.エンティティは次のようになります.
<?php
namespace App\Entity;
use App\Repository\IpBlockedRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=IpBlockedRepository::class)
*/
class IpBlocked
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/**
* @ORM\Column(type="string", length=255)
*/
private string $ipAddress;
/**
* @ORM\Column(type="datetime_immutable")
*/
private \DateTimeImmutable $blockedAt;
public function getId(): ?int
{
return $this->id;
}
public function getIpAddress(): ?string
{
return $this->ipAddress;
}
public function __construct(string $ipAddress)
{
date_default_timezone_set('Europe/Paris');
$this->ipAddress = $ipAddress;
$this->blockedAt = new \DateTimeImmutable('now');
}
public function getBlockedAt(): ?\DateTimeImmutable
{
return $this->blockedAt;
}
}
我々の特性に戻って、我々は現在最後の状態を書くことができます:if(count($repo->recentLoginAttempts($email)) === 5){
$blocked = new IpBlocked($ipAddress);
$manager->persist($blocked);
$manager->flush();
return $url->generate('app_account_blocked');
}
したがって、ユーザが5回目の接続を試みた場合、$ ipaddressをパラメータとして新しいipblockを呼び出します.あなたの特性は次のようになります.
<?php
namespace App\helper;
use App\Entity\IpBlocked;
use App\Repository\LoginAttemptRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
trait SecurityLoginAttemptTrait
{
public function secure(LoginAttemptRepository $repo,string $email, string $ipAddress, EntityManagerInterface $manager, UrlGeneratorInterface $url)
{
if(count($repo->recentLoginAttempts($email)) === 2){
throw new CustomUserMessageAuthenticationException('Il vous reste 3 essais');
}
if(count($repo->recentLoginAttempts($email)) === 3){
throw new CustomUserMessageAuthenticationException('Il vous reste 2 essais');
}
if(count($repo->recentLoginAttempts($email)) === 4){
throw new CustomUserMessageAuthenticationException('Attention c\'est votre dernier essai !');
}
if(count($repo->recentLoginAttempts($email)) === 5){
$blocked = new IpBlocked($ipAddress);
$manager->persist($blocked);
$manager->flush();
return $url->generate('app_account_blocked');
}
}
}
loginfoに戻る
checkCredentialsメソッドで作業する前に、新しいプライベートlogintry対面$ repoを作成し、コンストラクターに追加します.
では、メソッドを呼び出して安全なメソッドを呼び出します.パラメータで必要なことを思い出してください.
$this->secure($this->repo,$credentials['email'], $this->ipAddress, $this->entityManager, $this->urlGenerator);
を書くことができますそして、それは、我々のロジックが行われます.ユーザーが3分またはそれの下で5回接続しようとするならば、彼のIPアドレスは我々のデータベースにあります.
最後に
我々は、当社のウェブサイトからユーザーのアクセスをブロックしたい.匿名のユーザーが'/login 'と'/register 'にのみアクセスできることを忘れないでください.それから、ログインとレジスターのコントローラに行ってください.
IpBlockedRepository $ipBlockedRepo
Request $request
そして、最初の行があなたの状態を書きます.if ($ipBlockedRepo->findOneBy(['ipAddress' => $request->getClientIp()])){
return $this->redirectToRoute('app_account_blocked');
}
この論理で、ユーザーは接続するか、または登録することができません.もちろん、あなたは新しいルート' AppRange AccounttCountブロックを作成する必要がありますが、それは最も簡単なことです.まず、
symfony console make:controller AccountBlockedController
を作ることによって新しいコントローラを作成することから始めます次に、IPアドレスがブロックされていない場合、このページにアクセスできないようにします.したがって、RegisterControllerとLoginControllerと同じパラメータを追加してください.
if (!$ipBlockedRepo->findOneBy(['ipAddress' => $request->getClientIp()])){
return $this->redirectToRoute('app_login');
}
コントローラは次のようになります.<?php
namespace App\Controller;
use App\Repository\IpBlockedRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class AccountBlockedController extends AbstractController
{
/**
* @Route("/access-blocked", name="app_account_blocked")
*/
public function index(IpBlockedRepository $ipBlockedRepo, Request $request): Response
{
if (!$ipBlockedRepo->findOneBy(['ipAddress' => $request->getClientIp()])){
return $this->redirectToRoute('app_login');
}
return $this->render('account_blocked/index.html.twig', [
'controller_name' => 'AccountBlockedController',
]);
}
}
そして、あなたのテンプレートをパーソナライズし、ユーザーがなぜ彼のアクセスが禁止されている知っていることを忘れないでください.例えば、あなたは言うことができました:「あなたは、このウェブサイトへのアクセスを持っていません.」
そしてもちろん、あなたの連絡先ページへのアクセスをすべてのユーザーがブロックすることができます.
あなたがこの記事が好きで、あなたがどんな質問またはどんな改善でもあるならば、ちょっと私に知らせてください
乾杯!
Reference
この問題について(5.2のバージョンの下でSymfonyのログイン試み), 我々は、より多くの情報をここで見つけました https://dev.to/mis0u/login-attempt-in-symfony-under-5-2-version-njnテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol