feat: TOTP 2차 인증, 관리자 메뉴/대시보드 및 의존성 반영
- robthree/twofactorauth, Auth 설정·TotpService·2FA 뷰·라우트 - member TOTP 컬럼 DDL(login_tables, member_add_totp.sql) - 관리자 메뉴·레이아웃·필터·대시보드 등 연관 변경 - env 샘플에 auth.requireTotp 주석 Made-with: Cursor
This commit is contained in:
49
app/Libraries/TotpService.php
Normal file
49
app/Libraries/TotpService.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Libraries;
|
||||
|
||||
use Config\Auth as AuthConfig;
|
||||
use RobThree\Auth\Providers\Qr\QRServerProvider;
|
||||
use RobThree\Auth\TwoFactorAuth;
|
||||
|
||||
/**
|
||||
* TOTP 생성·검증·QR (robthree/twofactorauth)
|
||||
*/
|
||||
class TotpService
|
||||
{
|
||||
private TwoFactorAuth $tfa;
|
||||
|
||||
public function __construct(?AuthConfig $authConfig = null)
|
||||
{
|
||||
$authConfig ??= config('Auth');
|
||||
$this->tfa = new TwoFactorAuth(
|
||||
new QRServerProvider(),
|
||||
$authConfig->totpIssuer,
|
||||
);
|
||||
}
|
||||
|
||||
public function createSecret(): string
|
||||
{
|
||||
return $this->tfa->createSecret();
|
||||
}
|
||||
|
||||
public function verify(string $plainSecret, string $code): bool
|
||||
{
|
||||
$code = preg_replace('/\s+/', '', $code) ?? '';
|
||||
if (strlen($code) !== 6 || ! ctype_digit($code)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->tfa->verifyCode($plainSecret, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* PNG data URI (외부 QR API 호출 — 네트워크 필요)
|
||||
*/
|
||||
public function getQrDataUri(string $accountLabel, string $secret): string
|
||||
{
|
||||
return $this->tfa->getQRCodeImageAsDataUri($accountLabel, $secret);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user