-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3e25c03
Showing
12 changed files
with
1,379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
<?php | ||
|
||
namespace Plugin\TwoFactorAuthCustomerSms42\Controller; | ||
|
||
use Plugin\TwoFactorAuthCustomer42\Controller\TwoFactorAuthCustomerController; | ||
use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthSmsTypeCustomer; | ||
use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthPhoneNumberTypeCustomer; | ||
use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; | ||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; | ||
use Symfony\Component\HttpFoundation\RedirectResponse; | ||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
|
||
class TwoFactorAuthCustomerSmsController extends TwoFactorAuthCustomerController | ||
{ | ||
|
||
/** | ||
* SMS認証 送信先入力画面. | ||
* @Route("/two_factor_auth/tfa/sms/send_onetime", name="plg_customer_2fa_sms_send_onetime", methods={"GET", "POST"}) | ||
This comment has been minimized.
Sorry, something went wrong. |
||
* @Template("TwoFactorAuthCustomerSms42/Resource/template/default/tfa/sms/send.twig") | ||
*/ | ||
public function inputPhoneNumber(Request $request) | ||
{ | ||
if ($this->isAuth()) { | ||
return $this->redirectToRoute($this->getCallbackRoute()); | ||
} | ||
|
||
$error = null; | ||
/** @var Customer $Customer */ | ||
$Customer = $this->getUser(); | ||
$builder = $this->formFactory->createBuilder(TwoFactorAuthPhoneNumberTypeCustomer::class); | ||
$form = null; | ||
// 入力フォーム生成 | ||
$form = $builder->getForm(); | ||
|
||
// デバイス認証済み電話番号が設定済みの場合は優先して利用 | ||
$phoneNumber = ($Customer->getDeviceAuthedPhoneNumber() != null ? $Customer->getDeviceAuthedPhoneNumber() : $Customer->getTwoFactorAuthedPhoneNumber()); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
if ('POST' === $request->getMethod()) { | ||
$form->handleRequest($request); | ||
if ($form->isSubmitted()) { | ||
if ($Customer->isTwoFactorAuth() && $phoneNumber) { | ||
// 初回認証済み | ||
// 前回送信した電話番号へワンタイムコードを送信 | ||
$this->sendToken($Customer, $phoneNumber); | ||
$response = new RedirectResponse($this->generateUrl('plg_customer_2fa_sms_input_onetime')); | ||
// 送信電話番号をセッションへ一時格納 | ||
$this->session->set( | ||
CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER, | ||
$phoneNumber | ||
); | ||
return $response; | ||
} else { | ||
// 初回認証時 | ||
if ($form->isValid()) { | ||
$phoneNumber = $form->get('phone_number')->getData(); | ||
// 入力された電話番号へワンタイムコードを送信 | ||
$this->sendToken($Customer, $phoneNumber); | ||
$response = new RedirectResponse($this->generateUrl('plg_customer_2fa_sms_input_onetime')); | ||
// 送信電話番号をセッションへ一時格納 | ||
$this->session->set( | ||
CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER, | ||
$phoneNumber | ||
); | ||
return $response; | ||
} else { | ||
$error = trans('front.2fa.sms.send.failure_message'); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return [ | ||
'form' => $form->createView(), | ||
'Customer' => $Customer, | ||
'phoneNumber' => $phoneNumber, | ||
'error' => $error, | ||
]; | ||
} | ||
|
||
/** | ||
* SMS認証 ワンタイムトークン入力画面. | ||
* @Route("/two_factor_auth/tfa/sms/input_onetime", name="plg_customer_2fa_sms_input_onetime", methods={"GET", "POST"}) | ||
This comment has been minimized.
Sorry, something went wrong. |
||
* @Template("TwoFactorAuthCustomerSms42/Resource/template/default/tfa/sms/input.twig") | ||
*/ | ||
public function inputToken(Request $request) | ||
{ | ||
if ($this->isAuth()) { | ||
return $this->redirectToRoute($this->getCallbackRoute()); | ||
} | ||
|
||
$error = null; | ||
/** @var Customer $Customer */ | ||
$Customer = $this->getUser(); | ||
$builder = $this->formFactory->createBuilder(TwoFactorAuthSmsTypeCustomer::class); | ||
$form = null; | ||
$auth_key = null; | ||
// 入力フォーム生成 | ||
$form = $builder->getForm(); | ||
if ('POST' === $request->getMethod()) { | ||
$form->handleRequest($request); | ||
$token = $form->get('one_time_token')->getData(); | ||
if ($form->isSubmitted() && $form->isValid()) { | ||
if (!$this->checkToken($Customer, $token)) { | ||
// ワンタイムトークン不一致 or 有効期限切れ | ||
$error = trans('front.2fa.onetime.invalid_message__reinput'); | ||
} else { | ||
// 送信電話番号をセッションより取得 | ||
$phoneNumber = $this->session->get(CustomerTwoFactorAuthService::SESSION_AUTHED_PHONE_NUMBER); | ||
// ワンタイムトークン一致 | ||
// 二段階認証完了 | ||
$Customer->setTwoFactorAuth(true); | ||
$Customer->setTwoFactorAuthedPhoneNumber($phoneNumber); | ||
$this->entityManager->persist($Customer); | ||
$this->entityManager->flush(); | ||
|
||
$response = new RedirectResponse($this->generateUrl($this->getCallbackRoute())); | ||
$response->headers->setCookie( | ||
$this->customerTwoFactorAuthService->createAuthedCookie( | ||
$Customer, | ||
$this->getCallbackRoute() | ||
) | ||
); | ||
return $response; | ||
} | ||
} else { | ||
$error = trans('front.2fa.onetime.invalid_message__reinput'); | ||
} | ||
} | ||
|
||
return [ | ||
'form' => $form->createView(), | ||
'Customer' => $Customer, | ||
'error' => $error, | ||
]; | ||
} | ||
|
||
/** | ||
* ワンタイムトークンを送信. | ||
* | ||
* @param \Eccube\Entity\Customer $Customer | ||
* @param string $phoneNumber | ||
* | ||
*/ | ||
private function sendToken($Customer, $phoneNumber) | ||
{ | ||
// ワンタイムトークン生成・保存 | ||
$token = $Customer->createTwoFactorAuthOneTimeToken(); | ||
$this->entityManager->persist($Customer); | ||
$this->entityManager->flush(); | ||
|
||
// ワンタイムトークン送信メッセージをレンダリング | ||
$twig = 'TwoFactorAuthCustomer42/Resource/template/default/sms/onetime_message.twig'; | ||
$body = $this->twig->render($twig , [ | ||
'Customer' => $Customer, | ||
'token' => $token, | ||
]); | ||
|
||
// SMS送信 | ||
return $this->customerTwoFactorAuthService->sendBySms($Customer, $phoneNumber, $body); | ||
} | ||
|
||
/** | ||
* ワンタイムトークンチェック. | ||
* | ||
* @return boolean | ||
*/ | ||
private function checkToken($Customer, $token) | ||
{ | ||
$now = new \DateTime(); | ||
if ($Customer->getTwoFactorAuthOneTimeToken() !== $token | ||
|| $Customer->getTwoFactorAuthOneTimeTokenExpire() < $now) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
<?php | ||
|
||
namespace Plugin\TwoFactorAuthCustomerSms42\Entity; | ||
|
||
use Doctrine\ORM\Mapping as ORM; | ||
use Eccube\Annotation\EntityExtension; | ||
|
||
/** | ||
* @EntityExtension("Eccube\Entity\Customer") | ||
*/ | ||
trait CustomerTrait | ||
{ | ||
/** | ||
* @var string|null | ||
* | ||
* @ORM\Column(name="two_factor_authed_phone_number", type="string", length=14, nullable=true) | ||
*/ | ||
private $two_factor_authed_phone_number; | ||
|
||
/** | ||
* @var ?string | ||
* | ||
* @ORM\Column(name="two_factor_auth_one_time_token", type="string", length=10, nullable=true) | ||
*/ | ||
private ?string $two_factor_auth_one_time_token; | ||
|
||
/** | ||
* @var \DateTime|null | ||
* | ||
* @ORM\Column(name="two_factor_auth_one_time_token_expire", type="datetimetz", nullable=true) | ||
*/ | ||
private $two_factor_auth_one_time_token_expire; | ||
|
||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getTwoFactorAuthedPhoneNumber(): ?string | ||
{ | ||
return $this->two_factor_authed_phone_number; | ||
} | ||
|
||
/** | ||
* @param string $two_factor_authed_phone_number | ||
*/ | ||
public function setTwoFactorAuthedPhoneNumber(string $two_factor_authed_phone_number): void | ||
{ | ||
$this->two_factor_authed_phone_number = $two_factor_authed_phone_number; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function createTwoFactorAuthOneTimeToken(): ?string | ||
{ | ||
$now = new \DateTime(); | ||
|
||
// TODO: なんちゃって | ||
$token = ''; | ||
for ($i = 0; $i < 6; $i++) { | ||
$token .= (string)rand(0, 9); | ||
} | ||
|
||
$this->setTwoFactorAuthOneTimeToken($token); | ||
$this->setTwoFactorAuthOneTimeTokenExpire($now->modify('+5 mins')); | ||
return $token; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getTwoFactorAuthOneTimeToken(): ?string | ||
{ | ||
return $this->two_factor_auth_one_time_token; | ||
} | ||
|
||
/** | ||
* @param string $two_factor_auth_one_time_token | ||
*/ | ||
public function setTwoFactorAuthOneTimeToken(?string $two_factor_auth_one_time_token): void | ||
{ | ||
$this->two_factor_auth_one_time_token = $two_factor_auth_one_time_token; | ||
} | ||
|
||
/** | ||
* Set oneTimeTokenExpire. | ||
* | ||
* @param \DateTime|null $resetExpire | ||
* | ||
* @return Customer | ||
*/ | ||
public function setTwoFactorAuthOneTimeTokenExpire($deviceAuthOneTimeTokenExpire = null) | ||
{ | ||
$this->two_factor_auth_one_time_token_expire = $deviceAuthOneTimeTokenExpire; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Get resetExpire. | ||
* | ||
* @return \DateTime|null | ||
*/ | ||
public function getTwoFactorAuthOneTimeTokenExpire() | ||
{ | ||
return $this->two_factor_auth_one_time_token_expire; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of EC-CUBE | ||
* | ||
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved. | ||
* | ||
* http://www.ec-cube.co.jp/ | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Plugin\TwoFactorAuthCustomerSms42; | ||
|
||
use Eccube\Entity\BaseInfo; | ||
use Eccube\Repository\BaseInfoRepository; | ||
use Doctrine\ORM\EntityManagerInterface; | ||
use Eccube\Event\EccubeEvents; | ||
use Eccube\Event\EventArgs; | ||
use Eccube\Event\TemplateEvent; | ||
use Eccube\Request\Context; | ||
use Plugin\TwoFactorAuthCustomer42\Repository\BaseTwoFactorAuthSettingRepository; | ||
use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; | ||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
use Symfony\Component\DependencyInjection\ContainerInterface; | ||
use Symfony\Component\Filesystem\Filesystem; | ||
|
||
/** | ||
* Class Event. | ||
*/ | ||
class Event implements EventSubscriberInterface | ||
{ | ||
/** | ||
* @var ContainerInterface | ||
*/ | ||
protected $container; | ||
|
||
/** | ||
* @var BaseInfo | ||
*/ | ||
protected $BaseInfo; | ||
|
||
/** | ||
* @var CustomerTwoFactorAuthService | ||
*/ | ||
protected $customerTwoFactorAuthService; | ||
|
||
/** | ||
* @var EntityManagerInterface | ||
*/ | ||
private $entityManager; | ||
|
||
/** | ||
* @var \Twig_Environment | ||
*/ | ||
private $twig; | ||
|
||
/** | ||
* @var NotifierInterface | ||
*/ | ||
//private $notifier; | ||
|
||
/** | ||
* Event constructor. | ||
* | ||
* @param ContainerInterface $container | ||
* @param BaseInfoRepository $baseInfoRepository | ||
* @param EntityManagerInterface $entityManager | ||
* @param CustomerTwoFactorAuthService $customerTwoFactorAuthService | ||
* @param \Twig_Environment $twig | ||
*/ | ||
public function __construct( | ||
ContainerInterface $container, | ||
BaseInfoRepository $baseInfoRepository, | ||
EntityManagerInterface $entityManager, | ||
CustomerTwoFactorAuthService $customerTwoFactorAuthService, | ||
\Twig_Environment $twig | ||
) | ||
{ | ||
$this->container = $container; | ||
$this->BaseInfo = $baseInfoRepository->get(); | ||
$this->entityManager = $entityManager; | ||
$this->customerTwoFactorAuthService = $customerTwoFactorAuthService; | ||
$this->twig = $twig; | ||
} | ||
|
||
public static function getSubscribedEvents(): array | ||
{ | ||
return [ | ||
'@admin/Customer/edit.twig' => 'onRenderAdminCustomerEdit', | ||
]; | ||
} | ||
|
||
/** | ||
* [/admin/customer/edit]表示の時のEvent Fork. | ||
* 二段階認証関連項目を追加する. | ||
* | ||
* @param TemplateEvent $event | ||
*/ | ||
public function onRenderAdminCustomerEdit(TemplateEvent $event) | ||
{ | ||
// add twig | ||
$twig = 'TwoFactorAuthCustomerSms42/Resource/template/admin/customer_edit.twig'; | ||
$event->addSnippet($twig); | ||
} | ||
|
||
} |
Oops, something went wrong.
ログイン必須のルートは
/mypage/
以下に。