Symfony4로 로그인에 실패한 경우 로그에 출력
소개
공식 문서의 보안 과 How to Build a Login Form 를 보면서, 로그인 폼으로 로그인을 하는 샘플을 작성했습니다.
계속해서 로그인에 실패했을 경우에, 실패한 사람의 로그를 취득해 두고 싶습니다.
정책
How to Build a Login Form 로 작성한 경우, LoginFormAuthenticator.php
에 Logger 를 인젝션 해 출력하고 싶습니다.
이것을 하면 인증이라는 기능에 로깅이라는 다른 기능이 섞여 버리므로 잘 안되는 것 같습니다.
Symfony의 정석으로서는, 인증 종료 후에 Authentication Events 가 송신되므로, 이 이벤트를 기다리고 처리를 하는 것이 좋은 것 같습니다.
이벤트 리스너 작성
이벤트 리스너 클래스의 병아리 작성
Events and Event Listeners 을 읽으면서 이벤트 리스너를 만듭니다.
먼저 src
아래에 EventListener
디렉터리를 만듭니다.
해당 디렉토리 아래에 LoginLoggingListener
클래스를 만듭니다.
다음은 LoginLoggingListener
클래스의 골조입니다.EventSubscriberInterface
를 상속합니다.
/src/EventListener/LoginLoggingListener.php<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LoginLoggingListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
// TODO: Implement getSubscribedEvents() method.
}
}
청취할 이벤트 등록
이벤트 구독 등록은 Creating an Event Listener 을 살펴보면 service.yaml
에 기재하는 방법과 Creating an Event Subscriber 를 구현해 나가는 방법이 있습니다.
이번에는 Event Subscriber
를 구현합니다.
Authentication Events을 보면 로그인에 실패하면 security.authentication.failure
의 이벤트가 발생하므로 이것을 후크하면 좋을 것 같습니다.
후크 함수로서 loggingLoginFailure
메소드를 등록합니다. 두 번째 10
는 이 이벤트에 여러 후크 함수를 등록할 때 우선순위가 되는 번호입니다.
/src/EventListener/LoginLoggingListener.phpclass LoginLoggingListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
AuthenticationEvents::AUTHENTICATION_FAILURE => [
['loggingLoginFailure', 10]
]
];
}
}
이벤트 후크 함수 구현
훅 함수의 실태를 작성해 갑니다.
훅 함수에는 AuthenticationFailureEvent
가 건네집니다만, 원하는 정보는 들어가 있습니까?
일단 dd로 보자.
/src/EventListener/LoginLoggingListener.phpclass LoginLoggingListener implements EventSubscriberInterface
{
~~~ 省略 ~~~
public function loggingLoginFailure(AuthenticationFailureEvent $event):void
{
dd($event);
}
}
이런 식으로, 로그인 폼에 입력된 정보의 메일 주소, 패스워드는 잡혔습니다!
그러나 중요한 클라이언트의 IP 등은 들어 있지 않습니다.
Controller처럼 Request
빙글빙글 보니 같은 일을 하고 싶은 사람이 계셨습니다.
Symfony - How to get username and IP address in authentication failure listener?
분명히 RequestStack
를 주입하는 것이 좋습니다.
이 근처, 왜, RequestStack
가 좋은 것인지, 모르기 때문에, 누군가 자세한 분에게 가르쳐 주셨으면 합니다.
결국 LoggerInterface
도 주입하여 다음과 같이 되었습니다.
/src/EventListener/LoginLoggingListener.phpclass LoginLoggingListener implements EventSubscriberInterface
{
private $logger;
private $requestStack;
public function __construct(LoggerInterface $loginAuditLogger, RequestStack $requestStack)
{
$this->logger = $loginAuditLogger;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents()
{
return [
AuthenticationEvents::AUTHENTICATION_FAILURE => [
['LoggingLoginFailure', 10]
]
];
}
public function loggingLoginFailure(AuthenticationFailureEvent $event):void
{
$hCredentials = $event->getAuthenticationToken()->getCredentials();
$this->logger->notice(sprintf('[Login Failure] email: %s, password: %s, ip: %s, ua: %s, referer: %s',
$hCredentials['email'],
$hCredentials['password'],
$request->getClientIp(),
$request->headers->get('user-agent'),
$request->headers->get('referer')
));
}
}
이번 취지와 다릅니다만, 로그는 독자 파일(login_audit-xxxx.log)에 출력하고 있습니다.
/var/log/login_audit-2019-12-24.log[2019-12-24 16:43:15] login_audit.NOTICE: [Login Failure] email: [email protected], password: hogehoge, ip: 172.18.0.1, ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36, referer: https://localhost/login [] []
요약
Symfony에는 다양한 이벤트가 있기 때문에 그것을 사용하여 기능을 최소화하면 좋을 것 같네요.
이제 서비스라든지 번들이라든지, 이해하기 어려운 부분이 나왔기 때문에, 부담없이 일본어로 상담할 수 있는 멘터를 원하는 곳입니다.
Reference
이 문제에 관하여(Symfony4로 로그인에 실패한 경우 로그에 출력), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/idani/items/f5312af293c070e94821
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
How to Build a Login Form 로 작성한 경우,
LoginFormAuthenticator.php
에 Logger 를 인젝션 해 출력하고 싶습니다.이것을 하면 인증이라는 기능에 로깅이라는 다른 기능이 섞여 버리므로 잘 안되는 것 같습니다.
Symfony의 정석으로서는, 인증 종료 후에 Authentication Events 가 송신되므로, 이 이벤트를 기다리고 처리를 하는 것이 좋은 것 같습니다.
이벤트 리스너 작성
이벤트 리스너 클래스의 병아리 작성
Events and Event Listeners 을 읽으면서 이벤트 리스너를 만듭니다.
먼저 src
아래에 EventListener
디렉터리를 만듭니다.
해당 디렉토리 아래에 LoginLoggingListener
클래스를 만듭니다.
다음은 LoginLoggingListener
클래스의 골조입니다.EventSubscriberInterface
를 상속합니다.
/src/EventListener/LoginLoggingListener.php<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LoginLoggingListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
// TODO: Implement getSubscribedEvents() method.
}
}
청취할 이벤트 등록
이벤트 구독 등록은 Creating an Event Listener 을 살펴보면 service.yaml
에 기재하는 방법과 Creating an Event Subscriber 를 구현해 나가는 방법이 있습니다.
이번에는 Event Subscriber
를 구현합니다.
Authentication Events을 보면 로그인에 실패하면 security.authentication.failure
의 이벤트가 발생하므로 이것을 후크하면 좋을 것 같습니다.
후크 함수로서 loggingLoginFailure
메소드를 등록합니다. 두 번째 10
는 이 이벤트에 여러 후크 함수를 등록할 때 우선순위가 되는 번호입니다.
/src/EventListener/LoginLoggingListener.phpclass LoginLoggingListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
AuthenticationEvents::AUTHENTICATION_FAILURE => [
['loggingLoginFailure', 10]
]
];
}
}
이벤트 후크 함수 구현
훅 함수의 실태를 작성해 갑니다.
훅 함수에는 AuthenticationFailureEvent
가 건네집니다만, 원하는 정보는 들어가 있습니까?
일단 dd로 보자.
/src/EventListener/LoginLoggingListener.phpclass LoginLoggingListener implements EventSubscriberInterface
{
~~~ 省略 ~~~
public function loggingLoginFailure(AuthenticationFailureEvent $event):void
{
dd($event);
}
}
이런 식으로, 로그인 폼에 입력된 정보의 메일 주소, 패스워드는 잡혔습니다!
그러나 중요한 클라이언트의 IP 등은 들어 있지 않습니다.
Controller처럼 Request
빙글빙글 보니 같은 일을 하고 싶은 사람이 계셨습니다.
Symfony - How to get username and IP address in authentication failure listener?
분명히 RequestStack
를 주입하는 것이 좋습니다.
이 근처, 왜, RequestStack
가 좋은 것인지, 모르기 때문에, 누군가 자세한 분에게 가르쳐 주셨으면 합니다.
결국 LoggerInterface
도 주입하여 다음과 같이 되었습니다.
/src/EventListener/LoginLoggingListener.phpclass LoginLoggingListener implements EventSubscriberInterface
{
private $logger;
private $requestStack;
public function __construct(LoggerInterface $loginAuditLogger, RequestStack $requestStack)
{
$this->logger = $loginAuditLogger;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents()
{
return [
AuthenticationEvents::AUTHENTICATION_FAILURE => [
['LoggingLoginFailure', 10]
]
];
}
public function loggingLoginFailure(AuthenticationFailureEvent $event):void
{
$hCredentials = $event->getAuthenticationToken()->getCredentials();
$this->logger->notice(sprintf('[Login Failure] email: %s, password: %s, ip: %s, ua: %s, referer: %s',
$hCredentials['email'],
$hCredentials['password'],
$request->getClientIp(),
$request->headers->get('user-agent'),
$request->headers->get('referer')
));
}
}
이번 취지와 다릅니다만, 로그는 독자 파일(login_audit-xxxx.log)에 출력하고 있습니다.
/var/log/login_audit-2019-12-24.log[2019-12-24 16:43:15] login_audit.NOTICE: [Login Failure] email: [email protected], password: hogehoge, ip: 172.18.0.1, ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36, referer: https://localhost/login [] []
요약
Symfony에는 다양한 이벤트가 있기 때문에 그것을 사용하여 기능을 최소화하면 좋을 것 같네요.
이제 서비스라든지 번들이라든지, 이해하기 어려운 부분이 나왔기 때문에, 부담없이 일본어로 상담할 수 있는 멘터를 원하는 곳입니다.
Reference
이 문제에 관하여(Symfony4로 로그인에 실패한 경우 로그에 출력), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/idani/items/f5312af293c070e94821
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LoginLoggingListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
// TODO: Implement getSubscribedEvents() method.
}
}
class LoginLoggingListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
AuthenticationEvents::AUTHENTICATION_FAILURE => [
['loggingLoginFailure', 10]
]
];
}
}
class LoginLoggingListener implements EventSubscriberInterface
{
~~~ 省略 ~~~
public function loggingLoginFailure(AuthenticationFailureEvent $event):void
{
dd($event);
}
}
class LoginLoggingListener implements EventSubscriberInterface
{
private $logger;
private $requestStack;
public function __construct(LoggerInterface $loginAuditLogger, RequestStack $requestStack)
{
$this->logger = $loginAuditLogger;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents()
{
return [
AuthenticationEvents::AUTHENTICATION_FAILURE => [
['LoggingLoginFailure', 10]
]
];
}
public function loggingLoginFailure(AuthenticationFailureEvent $event):void
{
$hCredentials = $event->getAuthenticationToken()->getCredentials();
$this->logger->notice(sprintf('[Login Failure] email: %s, password: %s, ip: %s, ua: %s, referer: %s',
$hCredentials['email'],
$hCredentials['password'],
$request->getClientIp(),
$request->headers->get('user-agent'),
$request->headers->get('referer')
));
}
}
[2019-12-24 16:43:15] login_audit.NOTICE: [Login Failure] email: [email protected], password: hogehoge, ip: 172.18.0.1, ua: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36, referer: https://localhost/login [] []
Symfony에는 다양한 이벤트가 있기 때문에 그것을 사용하여 기능을 최소화하면 좋을 것 같네요.
이제 서비스라든지 번들이라든지, 이해하기 어려운 부분이 나왔기 때문에, 부담없이 일본어로 상담할 수 있는 멘터를 원하는 곳입니다.
Reference
이 문제에 관하여(Symfony4로 로그인에 실패한 경우 로그에 출력), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/idani/items/f5312af293c070e94821텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)