214 lines
5.6 KiB
PHP
214 lines
5.6 KiB
PHP
<?php
|
|
/**
|
|
* Sentinel SMS 매직링크 로그인 (PHP)
|
|
* - system: kngil
|
|
* - secret_key: MY_SECRET_KEY
|
|
*/
|
|
|
|
require_once __DIR__ . '/env.php';
|
|
kngil_start_session();
|
|
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
/* =========================
|
|
설정값
|
|
========================= */
|
|
$AUTH_SERVER = 'http://61.98.205.242:8075';
|
|
$SYSTEM = 'kngil';
|
|
$SECRET_KEY = '9f3b2e7a0a4f1f25c41c8c2367d04d54a89a2a5b2b189d63a99a0b874db4b27f';
|
|
|
|
/* =========================
|
|
입력 처리
|
|
========================= */
|
|
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
|
$mode = $_GET['mode'] ?? $input['mode'] ?? '';
|
|
|
|
/* =========================
|
|
JWT 생성 (HS256)
|
|
========================= */
|
|
function base64url_encode($data) {
|
|
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
|
}
|
|
|
|
function create_jwt($payload, $secret) {
|
|
$header = ['alg' => 'HS256', 'typ' => 'JWT'];
|
|
|
|
$segments = [];
|
|
$segments[] = base64url_encode(json_encode($header));
|
|
$segments[] = base64url_encode(json_encode($payload));
|
|
|
|
$signing_input = implode('.', $segments);
|
|
$signature = hash_hmac('sha256', $signing_input, $secret, true);
|
|
|
|
$segments[] = base64url_encode($signature);
|
|
return implode('.', $segments);
|
|
}
|
|
|
|
/* =========================
|
|
cURL JSON 요청
|
|
========================= */
|
|
function curl_json($url, $method = 'GET', $headers = [], $body = null) {
|
|
$ch = curl_init($url);
|
|
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_CUSTOMREQUEST => $method,
|
|
CURLOPT_HTTPHEADER => $headers,
|
|
CURLOPT_POSTFIELDS => $body,
|
|
CURLOPT_TIMEOUT => 10
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$err = curl_error($ch);
|
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
curl_close($ch);
|
|
|
|
if ($err) {
|
|
throw new Exception($err);
|
|
}
|
|
|
|
return [$code, $response];
|
|
}
|
|
|
|
try {
|
|
|
|
/* =========================
|
|
1️⃣ 매직링크 발급 요청
|
|
========================= */
|
|
if ($mode === 'request') {
|
|
|
|
$rawPhone = $input['phone'] ?? '';
|
|
$phone = preg_replace('/[^0-9]/', '', $rawPhone);
|
|
|
|
if (!$phone) {
|
|
echo json_encode([
|
|
'status' => 'error',
|
|
'message' => '휴대폰 번호를 입력하세요.'
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// JWT payload (3분 유효)
|
|
$payload = [
|
|
'system' => $SYSTEM,
|
|
'iat' => time(),
|
|
'exp' => time() + 180
|
|
];
|
|
|
|
$jwt = create_jwt($payload, $SECRET_KEY);
|
|
|
|
[$code, $res] = curl_json(
|
|
$AUTH_SERVER . '/auth/sentinel',
|
|
'POST',
|
|
[
|
|
'Authorization: Bearer ' . $jwt,
|
|
'Content-Type: application/json'
|
|
],
|
|
json_encode([
|
|
'phoneNumber' => $phone
|
|
])
|
|
);
|
|
|
|
$result = json_decode($res, true);
|
|
|
|
if (empty($result['token'])) {
|
|
throw new Exception('Sentinel token 발급 실패');
|
|
}
|
|
|
|
// ✅ token 반드시 저장
|
|
$_SESSION['sms_login'] = [
|
|
'phone' => $phone,
|
|
'token' => $result['token']
|
|
];
|
|
|
|
echo json_encode([
|
|
'status' => 'success'
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
/* =========================
|
|
2️⃣ 매직링크 상태 확인 → 자동 로그인
|
|
========================= */
|
|
if ($mode === 'status') {
|
|
|
|
if (
|
|
empty($_SESSION['sms_login']['token']) ||
|
|
empty($_SESSION['sms_login']['phone'])
|
|
) {
|
|
echo json_encode(['status' => 'pending']);
|
|
exit;
|
|
}
|
|
|
|
$token = $_SESSION['sms_login']['token'];
|
|
$phone = $_SESSION['sms_login']['phone'];
|
|
|
|
$payload = [
|
|
'system' => $SYSTEM,
|
|
'iat' => time(),
|
|
'exp' => time() + 180
|
|
];
|
|
|
|
$jwt = create_jwt($payload, $SECRET_KEY);
|
|
|
|
[$code, $res] = curl_json(
|
|
$AUTH_SERVER . '/auth/status?token=' . $token,
|
|
'GET',
|
|
[
|
|
'Authorization: Bearer ' . $jwt
|
|
]
|
|
);
|
|
|
|
$data = json_decode($res, true);
|
|
|
|
// 🔴 인증 완료 시 로그인 처리
|
|
if (!empty($data['loggedIn'])) {
|
|
|
|
$stmt = $pdo->prepare("
|
|
SELECT
|
|
member_id,
|
|
user_id,
|
|
user_nm,
|
|
auth_bc
|
|
FROM kngil.users
|
|
WHERE REPLACE(tel_no, '-', '') = :phone
|
|
AND use_yn = 'Y'
|
|
LIMIT 1
|
|
");
|
|
$stmt->execute([':phone' => $phone]);
|
|
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$user) {
|
|
throw new Exception('해당 번호로 등록된 사용자 없음');
|
|
}
|
|
|
|
// ✅ 기존 PW 로그인과 동일
|
|
$_SESSION['login'] = [
|
|
'member_id' => $user['member_id'],
|
|
'user_id' => $user['user_id'],
|
|
'user_nm' => $user['user_nm'],
|
|
'auth_bc' => $user['auth_bc']
|
|
];
|
|
|
|
unset($_SESSION['sms_login']);
|
|
|
|
echo json_encode([
|
|
'status' => 'success',
|
|
'message' => '자동 로그인 완료'
|
|
], JSON_UNESCAPED_UNICODE);
|
|
exit;
|
|
}
|
|
|
|
echo json_encode(['status' => 'pending']);
|
|
exit;
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
echo json_encode([
|
|
'error' => true,
|
|
'message' => $e->getMessage()
|
|
], JSON_UNESCAPED_UNICODE);
|
|
}
|