Programming/PHP / / 2022. 6. 23. 10:28

관리자 로그인에 구글 OTP 적용하기

728x90

우선 자신의 폰에 맞게 OTP 앱을 다운로드 받아서 설치합니다.

그리고 여기로 가셔서 파일을 다운로드 받습니다.

실제로 사용할 파일은 PHPGangsta 안에 있는 GoogleAuthenticator.php 이 파일입니다. 그러니 이 파일만 다운로드 받으셔도 됩니다.

설치를 원하는 환경이 PHP 5.6이어서 이 코드들은 PHP 5.5, 5.6에서 정상적으로 실행됩니다.

[테스트 페이지입니다.]

테스트를 하시려면 아이디/패스워드 모두 test입니다.

아이디와 패스워드를 입력하고 로그인 버튼을 누르면 위처럼 QR 코드가 뜹니다.

디비 연결은 되어 있지 않습니다. 테스트를 위해서...

<style>
.otp-popup { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none; }
.otp-popup-content { position: absolute; top: 350px; left: 50%; width: 300px; height: 320px; padding: 20px; background-color: rgb(255, 255, 255); border: 1px solid #ccc; box-shadow: 0 2px 3px 0 rgba(34, 36, 38, 0.15); transform: translateX(-50%) translateY(-50%); font-size: 12px; overflow-y: scroll; }
#btn-check-qr { background: #000; color: #fff; width: 150px; height: 24px; border: 0; }
</style>
<script src="://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(function() {
$("#btn-submit").on("click", function() {
const id = $("#user-id").val(), password = $("#user-password").val();
$.ajax({
url: "check-login.php",
type: "POST",
data: {
id,
password
},
dataType: "json",
success: function(res) {
if(res.fl == "success") {
$("#otp-image").attr("src", res.qr);
$("#user-id").val(res.userid);
$("#secret-code").val(res.secret);
$("#qr-image").val(res.qr);
$(".otp-popup").show();
}
}
});
});
$("#btn-check-qr").on("click", function() {
const code = $("#user-code").val();
if(code) {
$.ajax({
url: "check-code.php",
type: "POST",
data: {
userid: $("#user-id").val(),
secret: $("#secret-code").val(),
qr: $("#qr-image").val(),
code: code
},
success: function(res) {
if(res == true) {
$(location).attr("href", "admin/main");
} else {
alert("QR 코드 오류");
}
}
});
}
});
});
</script>
<form>
<input type="text" name="userid" id="user-id" required>
<input type="password" name="userpassword" id="user-password" required>
<button type="button" id="btn-submit">로그인</button>
</form>
<div class="otp-popup">
<div class="otp-popup-content">
<img src="" id="otp-image">
<form id="qr-form" method="post">
<input type="hidden" name="userid" id="user-id" value="">
<input type="hidden" name="secret" id="secret-code" value="">
<input type="hidden" name="qr" id="qr-image" value="">
<input type="text" name="user_code" id="user-code" value="" maxlength="6">
<button type="button" id="btn-check-qr">확인</button>
</form>
</div>
</div>
view raw google-otp.html hosted with ❤ by GitHub

<?php
$message = [];
if($_POST['id'] == 'test' && $_POST['password'] == 'test') {
require_once 'GoogleAuthenticator.php';
$ga = new PHPGangsta_GoogleAuthenticator();
$secret = $ga->createSecret();
$qrCodeUrl = $ga->getQRCodeGoogleUrl('test', $secret);
$message = [
'fl' => 'success',
'userid' => $_POST['id'],
'secret' => $secret,
'qr' => $qrCodeUrl
];
} else {
$message['fl'] = 'fail';
}
echo json_encode($message);
view raw check-login.php hosted with ❤ by GitHub

<?php
require_once 'GoogleAuthenticator.php';
$ga = new PHPGangsta_GoogleAuthenticator();
$code_verify = $ga->verifyCode($_POST['secret'], $_POST['code'], 2);
echo $code_verify;
view raw check-code.php hosted with ❤ by GitHub

파일 실행 순서는 이렇습니다.

  1. google-otp.html
    아이디(#user-id), 패스워드(#user-password)를 입력하고(여기에서는 테스트를 위해서 각각 test, test를 입력) 로그인(#btn-submit) 버튼을 클릭하면 line 9 ~ 29까지가 실행이 됩니다.
  2. check-login.php
    1번에서 입력한 아이디와 패스워드가 정확한지 line 3에서 체크를 합니다. 물론 실제로 사용을 하시려면 이 라인 위에서 디비와 통신을 해서 입력한 값이 정확한지 검사가 이루어져야 합니다. 여기에선 test/test가 맞다고 가정을 합니다. 코드는 굳이 수정할 부분은 없습니다. 모든 값들을 json 형태로 다시 넘겨줍니다.
  3. check-code.php
    1번의 line 19 ~ 27을 보시면 2번에서 보낸 값들을 나눠서 입력합니다. 값이 정상적으로 넘어왔다면 div.otp-popup을 화면에 띄웁니다. 이제 여기에서 뜬 QR 코드를 다운로드 받은 앱으로 비추면 숫자 123 456 이렇게 떨어져서 총 여섯 자리가 나옵니다. 이걸 입력하고 확인(#btn-check-qr) 버튼을 클릭하면 다시 ajax로 이 값이 맞는지 체크합니다. 값이 맞다면 불린값이 리턴되니 true에 맞춰서 무언가 처리를 하면 되지 않을까 싶습니다.
반응형