클라이언트에게 $_POST['email']
을 받으면
XXS 공격 방지를 위해 htmlspecialchars() 함수를 이용해 문자열로 변환합니다.
$email = htmlspecialchars($_POST['email']);
htmlspecialchars(): 문자열에서 특수문자를 HTML 코드형식으로 변환한다.
XXS 공격: 스크립트 코드를 삽입 해 개발자가 고려하지 않은 기능이 작동하게 하는 치명적일 수 있는 공격
변수 $email이 올바른 이메일 형식인지 체크합니다.
public function mailCheck($_str)
{
if (preg_match("/^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$/i", $_str) == false)
{
return false;
}
else
{
return true;
}
}
$emailChk = $this->mailCheck($email);
mailCheck(): 정규식을 사용하여 메일 주소의 패턴과 일치시킵니다. @ 기호 앞과 뒤에 문자가 있는지, @ 기호 뒤에 올바른 도메인 이름이 있는지 확인합니다.
이메일이 형식이 유효하면 데이터베이스에 이메일이 있는지 확인합니다.
public static function emailExistChk($data=null)
{
$email = $data;
$db = static::getDB();
$emailChk = $db->query("SELECT
idx
FROM DB.Table
WHERE email='$email'
");
$count = $emailChk->rowCount();
$row = $emailChk->fetch(PDO::FETCH_ASSOC);
$dataPack = array('count' => $count , 'row' => $row);
return $dataPack;
}
$emailExist= AdminMo::emailExistChk($email);
emailExistChk(): 인자값을 WHERE절로 구분해 데이터가 있는지 확인
DB에 매칭되는 데이터가 있을시 데이터의 row값과 idx값, 랜덤토큰값, 인증코드, ip, 시간을 저장합니다.
public function Common_RandomString($LENGTH = 32, $TYPE = NULL)
{
switch ($TYPE)
{
case 'RandEnDecryptKEY':
$characters = '0123456789';
$characters .= 'abcdef';
$characters .= 'ABCDEF';
$string_generated = '';
$nmr_loops = $LENGTH;
while ($nmr_loops--)
{
$string_generated .= $characters[mt_rand(0, strlen($characters) - 1)];
}
break;
case 'SignUpHistoryRandoms':
$characters = '123456789';
$string_generated = '';
$nmr_loops = $LENGTH;
while ($nmr_loops--)
{
$string_generated .= $characters[mt_rand(0, strlen($characters) - 1)];
}
break;
}
}
$adminIDX=$emailExist['row']['idx'];
$Token_Random=$this->Common_RandomString(32,'RandEnDecryptKEY');
$SignUpHistoryRandoms=$this->Common_RandomString(5,'SignUpHistoryRandoms');
$ipBring = $this->GetIPaddress();
$nowDate = date('Y-m-d H:i:s');
Common_RandomString(32,'RandEnDecryptKEY'): 0-9, 'abcdef', 'ABCDEF'를 지정, while문을 이용해 32번 반복합니다. 각 반복에서 mt_rand()함수를 사용하여 가능한 문자 범위 내에서 임의의 숫자를 생성해 문자를 선택해 추가합니다. 마지막으로 32자 랜덤 문자열을 반환합니다.
Common_RandomString(5,'SignUpHistoryRandoms'): 0-9를 지정 5자리 랜덤 문자열을 반환합니다.
저장된 정보들로 DB의 데이터를 저장하고 업데이트합니다.
$db = static::getDB();
$stat=$db->query("UPDATE DB.Table SET
loginToken='$Token_Random'
WHERE email='$email'
");
$stat2=$db->query("INSERT INTO DB.Table SET
adminIDX = '$adminIDX',
code = '$SignUpHistoryRandoms',
createTime = '$nowDate',
ipAddress = '$ipBring'
");
정보들을 이메일로 발송합니다.
public function emailSendForm($email=null,$body=null,$title=null)
{
Modules::PHPMailer();
// PHPMailer 선언
$mail = new PHPMailer(true);
// SMTP 서버 세팅
$mail->isSMTP();
try {
// 구글 smtp 설정
$mail->Host = "smtp.gmail.com";
// SMTP 암호화 여부
$mail->SMTPAuth = true;
// SMTP 포트
$mail->Port = 123;
// SMTP 보안 프초트콜
$mail->SMTPSecure = "ssl";
// gmail 유저 아이디
$mail->Username = "123@gmail.com";
// gmail 패스워드
$mail->Password ="123";
// 인코딩 셋
$mail->CharSet = 'utf-8';
$mail->Encoding = "base64";
// 보내는 사람
$mail->setFrom('123@gmail.com', 'customercenter');
// 받는 사람
$mail->AddAddress($email);
// 본문 html 타입 설정
$mail->isHTML(true);
// 제목
$mail->Subject = $title;
// 본문 (HTML 전용)
$mail->Body = $body;
// $mail->Body = 'Dear asurroixx,</br> We need to be sure it is you trying to log in to your Coin account. Here is your authentication code:'.$SignUpHistoryRandoms;
$mail->Send();
// echo "Message has been sent";
} catch (phpmailerException $e) {
// echo $e->errorMessage();
} catch (Exception $e) {
// echo $e->getMessage();
}
}
$body = $SignUpHistoryRandoms;
$title = '이메일 왔습니다';
$emailSend = $this->emailSendForm($email,$body,$title);
클라이언트에게 $_POST['email']
,$_POST['code']
를 받으면 htmlspecialchars() 함수를 이용해 문자열로 변환 후 아이피와 함께 배열에 담습니다.
public function GetIPaddress()
{
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
return $_SERVER['REMOTE_ADDR'];
}
$ipAddress=$this->GetIPaddress();
$code = htmlspecialchars($_POST['code']);
$email = htmlspecialchars($_POST['email']);
$paramArr = ['code' => $code,'email' => $email,'ipAddress' => $ipAddress];
GetIPaddress(): 프록시 서버에서 오고 있음을 나타내는 "HTTP_X_FORWARD_FORD" 헤더가 설정되어 있는지 확인합니다. 이 값이 설정된 경우, 이 헤더의 값을 "REMOTE_ADDR" 서버 변수에 할당한 다음 반환합니다. "HTTP_X_FORWARD_FORD" 헤더가 설정되지 않은 경우 "REMOTE_ADDR" 서버 변수를 반환합니다.
HTTP_X_FORWARD_FOR: HTTP 프록시 또는 로드 밸런서를 통해 웹 서버에 연결하는 클라이언트의 원래 IP 주소를 식별하는 데 사용되는 HTTP 헤더 필드입니다.
REMOTE_ADDR: 서버에 연결하는 클라이언트의 IP 주소를 보유하는 PHP의 서버 변수입니다. 클라이언트가 프록시 또는 로드 밸런서를 통해 연결하는 경우 REMOTE_ADDR 변수에는 클라이언트의 실제 IP 주소 대신 프록시 또는 로드 밸런서의 IP 주소가 포함됩니다.
배열에 담은값이 DB에 있는지 조회합니다.
public static function GetLogin($data=null)
{
$code=$data['code'];
$email=$data['email'];
$ipAddress=$data['ipAddress'];
$db = static::getDB();
$GetDump = $db->prepare("SELECT
A.adminIDX,
A.code
FROM DB.Table AS A
LEFT JOIN sendipay.Admin AS B
ON(A.adminIDX = B.idx)
WHERE B.email='$email' AND A.code='$code' AND A.ipAddress='$ipAddress'
ORDER BY A.idx DESC LIMIT 1;
");
$GetDump->execute();
$count = $GetDump->rowCount();
$row = $GetDump->fetch(PDO::FETCH_ASSOC);
return $row;
}
$getLogin=AdminMo::GetLogin($paramArr);
유효성을 통과하면 아이디의 adminIDX값을 가져와 쿠키를 만듭니다.
$adminIDX=$getLogin['adminIDX'];
$adCookieMake=$this->AdCookieMakeDo($adminIDX);
$globalCookie = $this->AdGlobalCookieMakeDo($adminIDX);
adminIDX와 suburl, 토큰과 아이피를 받아 adminIDX와 일치한 데이터의 토큰값을 업데이트하고 배열에 담고 encode화 합니다.
$adminIDX=$data;
$suburl = $this->SubDomain();
$randomToken=$this->Common_RandomString(32,'RandEnDecryptKEY');
$ipAddress=$this->GetIPaddress();
$db = static::getDB();
$stat=$db->prepare("UPDATE sendipay.Admin SET
loginToken='$randomToken'
WHERE idx='$adminIDX'
");
$stat->execute();
$tokenDataArr = ['idx' => $adminIDX,'token' => $randomToken,'ip' => $ipAddress];
$tokenDataArrEn = json_encode($tokenDataArr,JSON_UNESCAPED_UNICODE);
encode화한 배열을 암호화하고 세션이 시작되지않았으면 세션을 시작합니다. 'AdSession'이라는 세션 변수를 설정하고 $sessionArr 배열을 해당 변수에 직렬화된 문자열로 저장합니다.
$admin_LOGIN_KEY=DefinAll::admin_LOGIN_KEY;
$tokenEncrypt=$this->encrypt($tokenDataArrEn,$admin_LOGIN_KEY);
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
$sessionArr = ['idx'=>$adminIDX,'token'=>$randomToken];
$_SESSION['AdSession'] = serialize($sessionArr);
serialize(): 배열을 세션 변수에 저장할 수 있도록 문자열로 변환하는 데 사용됩니다.
AdCookie라는 이름과 암호화된 토큰값을 가지고있는 쿠키를 굽습니다.
$setCookie = setcookie("AdCookie", $tokenEncrypt, time() + (86400 * 30), "/", "".$suburl.'.1234.com');
로그인 화면을 출력해줍니다.
$redirectUri = "https://admin.1234.com";
$result=['result'=>'t','redirectUri'=>$redirectUri];
echo json_encode($result,JSON_UNESCAPED_UNICODE);