diff --git a/f_func/func.php b/f_func/func.php index 4cddb5b9..7e31a0a3 100644 --- a/f_func/func.php +++ b/f_func/func.php @@ -203,4 +203,26 @@ function toInt($val, $force=false){ return intval($val); } throw new InvalidArgumentException('올바르지 않은 타입형 :'.$val); -} \ No newline at end of file +} + +/** + * Generate a random string, using a cryptographically secure + * pseudorandom number generator (random_int) + * + * For PHP 7, random_int is a PHP core function + * For PHP 5.x, depends on https://github.com/paragonie/random_compat + * + * @param int $length How many characters do we want? + * @param string $keyspace A string of all possible characters + * to select from + * @return string + */ +function random_str($length, $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') +{ + $str = ''; + $max = mb_strlen($keyspace, '8bit') - 1; + for ($i = 0; $i < $length; ++$i) { + $str .= $keyspace[random_int(0, $max)]; + } + return $str; +} diff --git a/f_install/sql/common_schema.sql b/f_install/sql/common_schema.sql index ff4224c7..06722bcd 100644 --- a/f_install/sql/common_schema.sql +++ b/f_install/sql/common_schema.sql @@ -43,33 +43,12 @@ CREATE TABLE `member` ( ) ENGINE=InnoDB DEFAULT CHARSET=UTF8; - --- 인증 테이블 -CREATE TABLE `auth_kakao` ( - `no` BIGINT(20) NOT NULL AUTO_INCREMENT, - `id` BIGINT(20) NOT NULL COMMENT 'after signup', - `access_token` CHAR(128) NOT NULL COMMENT 'after token', - `refresh_token` CHAR(128) NOT NULL, - `expires` DATETIME NOT NULL, - `refresh_token_expires` DATETIME NOT NULL, - `datetime` DATETIME NOT NULL, - `email` VARCHAR(128) NOT NULL, - PRIMARY KEY (`no`), - INDEX `access_token` (`access_token`), - INDEX `id` (`id`), - INDEX `expires` (`expires`), - INDEX `email` (`email`), - INDEX `refresh_expires` (`refresh_token_expires`), - INDEX `datetime` (`datetime`) -) -ENGINE=InnoDB DEFAULT CHARSET=UTF8; - -- 로그인 로그 테이블 CREATE TABLE `member_log` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `member_no` INT(11) NOT NULL, `date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `action_type` ENUM('reg','try_login','login','logout','oauth','make_general','access_server') NOT NULL, + `action_type` ENUM('reg','try_login','login','logout','oauth','change_pw','make_general','access_server') NOT NULL, `action` TEXT NULL DEFAULT NULL COMMENT 'JSON', PRIMARY KEY (`id`), INDEX `action` (`member_no`, `action_type`, `date`), diff --git a/tmp_kakao/index.php b/tmp_kakao/index.php index e0fb31b6..d8acebc3 100644 --- a/tmp_kakao/index.php +++ b/tmp_kakao/index.php @@ -53,7 +53,7 @@ function doLoginUsingOAuth(retry=false){ alert(obj.reason); } else{ - getOAuthToken(); + getOAuthToken('login'); } } else{ @@ -71,6 +71,9 @@ function postOAuthResult(result){ if(oauthMode=='change_pw'){ sendTempPasswordToKakaoTalk(); } + else{ + doLoginUsingOAuth(); + } } else{ alert('예외 발생!'); diff --git a/tmp_kakao/j_change_pw.php b/tmp_kakao/j_change_pw.php index 566dcdbc..7d915601 100644 --- a/tmp_kakao/j_change_pw.php +++ b/tmp_kakao/j_change_pw.php @@ -1,6 +1,118 @@ isLoggedIn()){ + returnJson([ + 'result'=>false, + 'reason'=>'로그인이 되어있지 않습니다' + ]); +} +$userID = $SESSION->NoMember(); +$access_token = util::array_get($_SESSION['access_token']); +$expires = util::array_get($_SESSION['expires']); +$refresh_token = util::array_get($_SESSION['refresh_token']); +$refresh_token_expires = util::array_get($_SESSION['refresh_token_expires']); + +if(!$access_token || !$expires){ + returnJson([ + 'result'=>false, + 'reason'=>'카카오로그인이 이루어지지 않았습니다.' + ]); +} + + +//TODO: join과 login의 동작이 비슷하다. helper class로 묶자. +$restAPI = new Kakao_REST_API_Helper($access_token); + +if($expires < $nowDate && (!$refresh_token || ($refresh_token_expires < $nowDate))){ + returnJson([ + 'result'=>false, + 'reason'=>'로그인 토큰 만료.'.$refresh_token_expires.' 다시 카카오로그인을 수행해주세요.' + ]); +} + +if($expires < $nowDate){ + unset($_SESSION['kaccount_email']); + $email = null; + + $result = $restAPI->refresh_access_token($refresh_token); + if(!isset($refresh_token)){ + returnJson([ + 'result'=>false, + 'reason'=>'카카오 로그인 과정 중 추가 갱신 절차를 실패했습니다' + ]); + } + + $access_token = $result['access_token']; + $expires = _Time::DatetimeFromNowSecond($nowDate, $result['expires_in']); + if(isset($result['refresh_token'])){ + $refresh_token = util::array_get($result['refresh_token']); + $refresh_token_expires = _Time::DatetimeFromNowSecond($nowDate, $result['refresh_token_expires_in']); + } +} + +getRootDB()->query("lock tables member write, member_log write"); + +$isUser = getRootDB()->queryFirstRow( + 'SELECT count(`no`) from member where no=%i',$userID); +if(!$isUser){ + returnJson([ + 'result'=>false, + 'reason'=>'회원이 아닙니다. 관리자에게 문의해주세요.' + ]); +} + +$newPassword = random_str(6); +$tmpPassword = hashPassword(getGlobalSalt(), $newPassword); +$newSalt = bin2hex(random_bytes(8)); +$newFinalPassword = hashPassword($newSalt, $tmpPassword); + +$sendResult = $restAPI->talk_to_me_default([ + "object_type"=> "text", + "text"=> "임시 비밀번호는 $newPassword 입니다. 로그인 후 바로 다른 비밀번호로 변경해주세요.", + "link"=> [ + "web_url"=> getServerBasepath(), + "mobile_web_url" => getServerBasepath() + ], + "button_title"=> "로그인 페이지 열기" +]); +$sendResult['code'] = util::array_get($sendResult['code'], 0); +if($sendResult['code'] < 0){ + returnJson([ + 'result'=>false, + 'reason'=>'카카오톡 메시지를 보내지 못했습니다.' + ]); +} + +getRootDB()->update('member', [ + 'pw'=>$newFinalPassword, + 'salt'=>$newSalt +],'no=%i', $userID); + +getRootDB()->insert('member_log', [ + 'member_no'=>$userID, + 'date'=>$nowDate, + 'action_type'=>'change_pw', + 'action'=>json_encode([ + 'type'=>'kakao', + 'no'=>$userID, + 'token'=>$access_token + ], JSON_UNESCAPED_UNICODE) +]); + +getRootDB()->query("unlock tables"); + + +returnJson([ + 'result'=>true, + 'reason'=>'success' +]); \ No newline at end of file diff --git a/tmp_kakao/j_join_process.php b/tmp_kakao/j_join_process.php index 00b34993..73eb960f 100644 --- a/tmp_kakao/j_join_process.php +++ b/tmp_kakao/j_join_process.php @@ -1,7 +1,7 @@ insert('auth_kakao',[ - 'id'=>$kakaoID, - 'access_token'=>$access_token, - 'refresh_token'=>$refresh_token, - 'expires'=>$expires, - 'refresh_token_expires'=>$refresh_token_expires, - 'datetime'=>$nowDate, - 'email'=>$email -]); - getRootDB()->insert('member',[ 'oauth_id' => $kakaoID, 'oauth_type' => 'KAKAO', diff --git a/tmp_kakao/kakao.php b/tmp_kakao/kakao.php index e822930e..1e6f7ad2 100644 --- a/tmp_kakao/kakao.php +++ b/tmp_kakao/kakao.php @@ -232,7 +232,11 @@ class Kakao_REST_API_Helper } public function talk_to_me_default($req){ - return $this->request(TalkPath::$TALK_TO_ME_DEFAULT, json_encode($req), 'POST'); + + $params = [ + 'template_object' => json_encode($req) + ]; + return $this->request(Talk_Path::$TALK_TO_ME_DEFAULT, $params, 'POST'); } diff --git a/tmp_kakao/lib.join.php b/tmp_kakao/lib.join.php index c3677cfb..75c50d98 100644 --- a/tmp_kakao/lib.join.php +++ b/tmp_kakao/lib.join.php @@ -2,7 +2,7 @@ require_once('_common.php'); require_once(__dir__.'/../d_setting/conf.php'); require_once(__dir__.'/../f_func/func.php'); -require(ROOT.'/f_func/class._Time.php'); +require_once(ROOT.'/f_func/class._Time.php'); function checkUsernameDup($username){ if(!$username){ diff --git a/twe/func.php b/twe/func.php index 1959456a..495a1dce 100644 --- a/twe/func.php +++ b/twe/func.php @@ -41,7 +41,7 @@ function randBool($prob = 0.5){ } /** - * 로그인한 유저의 전역 id를 받아옴 + * 로그인한 유저의 전역 id(숫자)를 받아옴 * * @return int|null */