카카오 로그인 초기 구현

This commit is contained in:
2018-09-09 20:19:00 +09:00
parent 5b7eba61cc
commit 15d43c9653
13 changed files with 458 additions and 47 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ if($expires < $nowDate){
$email = null;
$result = $restAPI->refresh_access_token($refresh_token);
if(!isset($refresh_token)){
if(!isset($result)){
Json::die([
'result'=>false,
'reason'=>'카카오 로그인 과정 중 추가 갱신 절차를 실패했습니다'
+92
View File
@@ -0,0 +1,92 @@
<?php
namespace sammo;
require(__dir__.'/../vendor/autoload.php');
$RootDB = RootDB::db();
$session = Session::getInstance();
if($session->isLoggedIn()){
Json::die([
'result'=>false,
'reset'=>true,
'reason'=>'이미 로그인 되어있습니다.'
]);
}
if(!$session->isLoggedIn(true)){
Json::die([
'result'=>false,
'reset'=>true,
'reason'=>'인증 코드를 입력할 수 있는 상태가 아닙니다.'
]);
}
$otp = Util::getReq('otp', 'int');
if(!$otp){
Json::die([
'result'=>false,
'reset'=>false,
'reason'=>'인증 코드가 입력되지 않았습니다.'
]);
}
$userNo = $session->getUserID();
$oauthInfo = Json::decode(RootDB::db()->queryFirstField('SELECT oauth_info FROM member WHERE no=%i', $userNo))??[];
if(!$oauthInfo){
$session->logout();
Json::die([
'result'=>false,
'reset'=>true,
'reason'=>'계정이 정상적으로 등록되어있지 않습니다.'
]);
}
$OTPValue = $oauthInfo['OTPValue']??null;
$OTPTrialUntil = $oauthInfo['OTPTrialUntil']??null;
$OTPTrialCount = $oauthInfo['OTPTrialCount']??0;
$now = TimeUtil::DatetimeNow();
if(!$OTPTrialUntil || $OTPTrialUntil <= $now){
$session->logout();
Json::die([
'result'=>false,
'reset'=>true,
'reason'=>'인증 기한이 만료되었습니다. 다시 로그인해주세요.'
]);
}
if($OTPTrialCount <= 0){
Json::die([
'result'=>false,
'reset'=>false,
'reason'=>"인증 실패 횟수를 초과했습니다. {$OTPTrialUntil}까지 기다려주세요."
]);
}
if($OTPValue != $otp){
$OTPTrialCount -= 1;
$oauthInfo['OTPTrialCount'] = $OTPTrialCount;
RootDB::db()->update('member', [
'oauth_info'=>Json::encode($oauthInfo)
], 'no=%i', $userNo);
Json::die([
'result'=>false,
'reset'=>false,
'reason'=>"인증 번호가 틀렸습니다. {$OTPTrialCount}회 더 시도할 수 있습니다."
]);
}
$OTPValidUntil = TimeUtil::DatetimeFromNowDay(10);
$session->setReqOTP(false);
$oauthInfo['OTPValidUntil'] = $OTPValidUntil;
RootDB::db()->update('member', [
'oauth_info'=>Json::encode($oauthInfo)
], 'no=%i', $userNo);
Json::die([
'result'=>true,
'reset'=>false,
'reason'=>"로그인을 성공했습니다."
]);
+16 -5
View File
@@ -125,23 +125,28 @@ if(!$kakaoID && Util::array_get($signupResult['msg'])!='already registered'){
$me = $restAPI->meWithEmail();
$me['code'] = Util::array_get($me['code'], 0);
$kakao_account = $me['kakao_account']??[];
if ($me['code']< 0) {
$restAPI->unlink();
Json::die([
'result'=>false,
'reason'=>'카카오로그인이 정상적으로 수행되지 않았습니다.'
'reason'=>'카카오로그인이 정상적으로 수행되지 않았습니다.',
]);
}
if(!Util::array_get($me['kaccount_email_verified'],false)){
$validEmail = $kakao_account['is_email_valid']??false;
$verifiedEmail = $kakao_account['is_email_verified']??false;
if(!$validEmail || !$verifiedEmail){
$restAPI->unlink();
Json::die([
'result'=>false,
'reason'=>'카카오 계정 이메일이 아직 인증되지 않았습니다'
'reason'=>'카카오 계정 이메일이 아직 인증되지 않았습니다',
'aux'=>$me
]);
}
$email = $me['kaccount_email'];
$email = $kakao_account['email']??null;
$session->kaccount_email = $email;
$emailChk = checkEmailDup($email);
if($emailChk !== true){
@@ -162,7 +167,13 @@ RootDB::db()->insert('member',[
'pw' => $finalPassword,
'salt' => $userSalt,
'name'=>$nickname,
'reg_date'=>$nowDate
'reg_date'=>$nowDate,
'oauth_info'=>Json::encode([
'accessToken'=>$access_token,
'refreshToken'=>$refresh_token,
'accessTokenValidUntil'=>$expires,
'refreshTokenValidUntil'=>$refresh_token_expires
])
]);
$userID = RootDB::db()->insertId();
+74 -12
View File
@@ -2,7 +2,7 @@
namespace sammo;
require(__dir__.'/../vendor/autoload.php');
require('lib.join.php');
use \kakao\Kakao_REST_API_Helper as Kakao_REST_API_Helper;
$RootDB = RootDB::db();
@@ -15,12 +15,13 @@ $canLogin = RootDB::db()->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `N
if($canLogin != 'Y'){
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'현재는 로그인이 금지되어있습니다!',
'noRetry'=>true
]);
}
$nowDate = TimeUtil::DatetimeNow();
$now = TimeUtil::DatetimeNow();
$access_token = $session->access_token;
$expires = $session->expires;
@@ -32,6 +33,7 @@ $email = $session->kaccount_email;
if(!$access_token || !$expires){
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'카카오로그인이 이루어지지 않았습니다.'
]);
}
@@ -39,14 +41,15 @@ if(!$access_token || !$expires){
//TODO: join과 login의 동작이 비슷하다. helper class로 묶자.
$restAPI = new Kakao_REST_API_Helper($access_token);
if($expires < $nowDate && (!$refresh_token || ($refresh_token_expires < $nowDate))){
if($expires < $now && (!$refresh_token || ($refresh_token_expires < $now))){
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'로그인 토큰 만료.'.$refresh_token_expires.' 다시 카카오로그인을 수행해주세요.'
]);
}
if($expires < $nowDate){
if($expires < $now){
$session->kaccount_email = null;
$email = null;
@@ -54,6 +57,7 @@ if($expires < $nowDate){
if(!isset($refresh_token)){
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'카카오 로그인 과정 중 추가 갱신 절차를 실패했습니다'
]);
}
@@ -73,43 +77,69 @@ if(!$email){
if ($me['code']< 0) {
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'카카오로그인이 정상적으로 수행되지 않았습니다.'
]);
}
if(!Util::array_get($me['kaccount_email_verified'],false)){
$kakao_account = $me['kakao_account']??null;
if (!$kakao_account) {
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'카카오 로그인 정보를 제대로 받아오지 못했습니다.'
]);
}
if(!($kakao_account['has_email']??false)){
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'이메일 정보 공유를 허락해 주셔야 합니다.',
'aux'=>$me
]);
}
$validEmail = $kakao_account['is_email_valid']??false;
$verifiedEmail = $kakao_account['is_email_verified']??false;
if(!$validEmail || !$verifiedEmail){
$restAPI->unlink();
Json::die([
'result'=>false,
'reason'=>'카카오 계정 이메일이 아직 인증되지 않았습니다'
'reqOTP'=>false,
'reason'=>'카카오 계정 이메일이 아직 인증되지 않았습니다',
]);
}
$email = $me['kaccount_email'];
$email = $kakao_account['email'];
$session->kaccount_email = $email;
}
$userInfo = $RootDB->queryFirstRow(
'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl` from member where email=%s',$email);
'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl`, oauth_info from member where email=%s',$email);
if(!$userInfo){
$restAPI->unlink();
$session->access_token = null;
Json::die([
'result'=>false,
'reason'=>'카카오로그인에 해당하는 계정이 없습니다. 재 가입을 시도해주세요.'
'reqOTP'=>false,
'reason'=>'카카오로그인에 해당하는 계정이 없습니다. 재 가입을 시도해주세요.',
'aux'=>$session->tmpx,
]);
}
if($userInfo['delete_after']){
if($userInfo['delete_after'] < $nowDate){
if($userInfo['delete_after'] < $now){
$restAPI->unlink();
$session->access_token = null;
$RootDB->delete('member', 'no=%i', $userInfo['no']);
Json::die([
'result'=>false,
'reason'=>"기간 만기로 삭제되었습니다. 재 가입을 시도해주세요."
'reqOTP'=>false,
'reason'=>"기간 만기로 삭제되었습니다. 재 가입을 시도해주세요.",
]);
}
else{
@@ -117,12 +147,43 @@ if($userInfo['delete_after']){
$session->access_token = null;
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>"삭제 요청된 계정입니다.[{$userInfo['delete_after']}]"
]);
}
}
$oauthInfo = Json::decode($userInfo['oauth_info'])??[];
$oauthInfo['accessToken'] = $access_token;
$oauthInfo['refreshToken'] = $refresh_token;
$oauthInfo['accessTokenValidUntil'] = $expires;
$oauthInfo['refreshTokenValidUntil'] = $refresh_token_expires;
RootDB::db()->update('member', [
'oauth_info'=>Json::encode($oauthInfo)
], 'no=%i', $userInfo['no']);
$OTPValidUntil = $oauthInfo['OTPValidUntil']??null;
if(!$OTPValidUntil || $OTPValidUntil < $now){
if(!createOTPbyUserNO($userInfo['no'])){
Json::die([
'result'=>false,
'reqOTP'=>false,
'reason'=>'인증 코드를 보내는데 실패했습니다.'
]);
}
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], true, Json::decode($userInfo['acl']??'{}'));
Json::die([
'result'=>false,
'reqOTP'=>true,
'reason'=>'인증 코드를 입력해주세요.'
]);
}
$RootDB->insert('member_log',[
'member_no'=>$userInfo['no'],
'action_type'=>'login',
@@ -132,8 +193,9 @@ $RootDB->insert('member_log',[
])
]);
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], Json::decode($userInfo['acl']??'{}'));
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], false, Json::decode($userInfo['acl']??'{}'));
Json::die([
'result'=>true,
'reqOTP'=>false,
'reason'=>'로그인 되었습니다.'
]);
+65 -1
View File
@@ -1,5 +1,6 @@
<?php
namespace sammo;
use \kakao\Kakao_REST_API_Helper as Kakao_REST_API_Helper;
function checkUsernameDup($username){
if(!$username){
@@ -62,4 +63,67 @@ function checkEmailDup($email){
RootDB::db()->delete('member', 'no=%i', $userInfo['no']);
}
return true;
}
}
function createOTPbyUserNO(int $userNo):bool{
$userInfo = RootDB::db()->queryFirstRow('SELECT oauth_info FROM member WHERE no=%i', $userNo);
if(!$userInfo){
return false;
}
$oauthInfo = Json::decode($userInfo['oauth_info']);
if(!$oauthInfo){
return false;
}
$accessToken = $oauthInfo['accessToken'];
$OTPValue = $oauthInfo['OTPValue']??null;
$OTPTrialUntil = $oauthInfo['OTPTrialUntil']??null;
$now = TimeUtil::DatetimeNow();
if($OTPTrialUntil && $OTPValue && $OTPTrialUntil > $now){
return true;
}
[$OTPValue, $OTPTrialUntil] = createOTP($accessToken);
if(!$OTPValue){
return false;
}
$oauthInfo['OTPValue'] = $OTPValue;
$oauthInfo['OTPTrialUntil'] = $OTPTrialUntil;
$oauthInfo['OTPTrialCount'] = 3;
RootDB::db()->update('member', [
'oauth_info'=>Json::encode($oauthInfo)
], 'no=%i', $userNo);
return true;
}
function createOTP(string $accessToken):array{
$restAPI = new Kakao_REST_API_Helper($accessToken);
$OTPValue = Util::randRangeInt(10000, 99999);
$OTPTrialUntil = TimeUtil::DatetimeFromNowSecond(180);
$sendResult = $restAPI->talk_to_me_default([
"object_type"=> "text",
"text"=> "인증 코드는 $OTPValue 입니다. $OTPTrialUntil 이내에 입력해주세요.",
"link"=> [
"web_url"=> ServConfig::getServerBasepath(),
"mobile_web_url" => ServConfig::getServerBasepath()
],
"button_title"=> "로그인 페이지 열기"
]);
$sendResult['code'] = Util::array_get($sendResult['code'], 0);
if($sendResult['code'] < 0){
return null;
}
return [$OTPValue, $OTPTrialUntil];
}
+7 -2
View File
@@ -47,7 +47,12 @@ $me = $restAPI->meWithEmail();
$oauth_mode = 'login';
$me['code'] = Util::array_get($me['code'], 0);
if($me['code']< 0){
$signed = $me['has_signed_up']??false;
$kakao_account = $me['kakao_account']??[];
if(!$signed){
$oauth_mode = 'join';
}
else if($me['code']< 0){
switch(Util::array_get($me['msg'])){
case 'NotRegisteredUserException':
$oauth_mode = 'join';
@@ -57,7 +62,7 @@ if($me['code']< 0){
}
}
else{
$session->kaccount_email = $me['kaccount_email'];
$session->kaccount_email = $$kakao_account['email'];
}
?>