BARON-SSO 로그인 연동

This commit is contained in:
root
2026-07-27 17:23:52 +09:00
parent bf5e694571
commit ac5823234e
44 changed files with 1804 additions and 695 deletions
-13
View File
@@ -112,19 +112,6 @@
</body>
<script>
$(function(){
// footer family site toggle
$('.family_btn').click(function(e){
e.stopPropagation();
$('.family_list, .family_btn').toggleClass('family_on');
});
$(document).click(function(e){
if(!$(e.target).closest('.family_wrap').length){
$('.family_list, .family_btn').removeClass('family_on');
}
});
});
// 회원 탈퇴
function member_leave() {
if (confirm("회원에서 탈퇴 하시겠습니까?"))
+15 -25
View File
@@ -1,25 +1,7 @@
<?php
session_start();
require_once dirname(__DIR__, 4) . '/auth/common.php';
function set_descope_session_cookies(array $user): void {
$expire = time() + 86400;
$cookieOptions = [
'expires' => $expire,
'path' => '/',
'samesite' => 'Lax',
];
$customAttributes = $user['customAttributes'] ?? [];
$roleNames = $user['roleNames'] ?? [];
setcookie('descope_login_id', (string)($user['loginIds'][0] ?? ''), $cookieOptions);
setcookie('descope_user_id', (string)($user['userId'] ?? ''), $cookieOptions);
setcookie('descope_user_name', (string)($user['name'] ?? ''), $cookieOptions);
setcookie('descope_user_email', (string)($user['email'] ?? ''), $cookieOptions);
setcookie('descope_user_phone', (string)($user['phone'] ?? ''), $cookieOptions);
setcookie('descope_custom_attributes', base64_encode(json_encode($customAttributes, JSON_UNESCAPED_UNICODE)), $cookieOptions);
setcookie('descope_role_names', base64_encode(json_encode($roleNames, JSON_UNESCAPED_UNICODE)), $cookieOptions);
}
auth_session_start_if_needed();
$email = trim($_POST['mb_id'] ?? '');
$password = trim($_POST['mb_password'] ?? '');
@@ -60,16 +42,24 @@ if ($http_code === 200 && isset($res_data['sessionJwt'])) {
// 로그인 성공 → 실패횟수 초기화
$_SESSION['login_fail_count'] = 0;
//session으로도 저장
$_SESSION['user'] = $res_data['user']; // userId, email 등
$_SESSION['sessionJwt'] = $res_data['sessionJwt'];
$_SESSION['refreshJwt'] = $res_data['refreshJwt'];
set_descope_session_cookies($res_data['user'] ?? []);
$normalizedUser = auth_apply_user_session(
$res_data['user'] ?? [],
'descope',
[
'sessionJwt' => $res_data['sessionJwt'] ?? '',
'refreshJwt' => $res_data['refreshJwt'] ?? '',
]
);
setcookie('baron_user', '', auth_cookie_options(time() - 42000));
setcookie('baron_claims', '', auth_cookie_options(time() - 42000));
setcookie('baron_provider', '', auth_cookie_options(time() - 42000));
auth_set_descope_session_cookies($normalizedUser);
echo json_encode([
'status' => 'ok',
'sessionJwt' => $res_data['sessionJwt'] ?? '',
// 'refreshJwt' => $res_data['refreshJwt'] ?? '',
'user' => $res_data['user'] ?? [],
'user' => $normalizedUser,
'session' => $_SESSION,
]);
// } else {
+3 -10
View File
@@ -1,4 +1,5 @@
<?php
require_once dirname(__DIR__, 4) . '/auth/common.php';
// descope_logout.php
// session_start();
// $_SESSION = [];
@@ -16,17 +17,9 @@
// http_response_code(200);
// echo json_encode(['status'=>'ok']);
// exit;
session_start();
auth_session_start_if_needed();
$_SESSION = [];
foreach (['PHPSESSID', 'G5sessphp', 'descope_login_id', 'descope_user_id', 'descope_user_name', 'descope_user_email', 'descope_user_phone', 'descope_custom_attributes', 'descope_role_names'] as $cookieName) {
setcookie($cookieName, '', [
'expires' => time() - 42000,
'path' => '/',
'samesite' => 'Lax',
]);
}
auth_clear_all_cookies();
session_destroy();
http_response_code(200);
+7 -144
View File
@@ -1,148 +1,11 @@
<?php
// // descope_session.php
require_once dirname(__DIR__, 4) . '/auth/common.php';
// // 1) 에러 출력 (개발용)
// // ini_set('display_errors', 1);
// // error_reporting(E_ALL);
$authState = auth_sync_gnuboard_session();
// // 2) 세션 시작 (중복 호출 방지)
// if (session_status() === PHP_SESSION_NONE) {
// session_start();
// }
// // 3) 로그인 검사
// // 로그인 시 $_SESSION['user']['userId'] 와 $_SESSION['user']['loginIds'][0] 를 설정해 두었다면
// // if (empty($_SESSION['user']['userId'])) {
// // // 로그인 필요 알림 후 로그인 페이지로 이동
// // echo <<<HTML
// // <script>
// // alert('Q&A를 이용하시려면 로그인이 필요합니다.');
// // window.location.href = '/egbim/index.php';
// // </script>
// // HTML;
// // exit;
// // }
// // ✅ Descope 로그인 성공 시 g5_member 세션 동기화
// $loginId = $_SESSION['user']['loginIds'][0] ?? '';
// if ($loginId === 'b24014@hanmaceng.co.kr') {
// // g5_member 계정이 이미 존재한다고 가정
// $_SESSION['ss_mb_id'] = $loginId;
// $_SESSION['ss_mb_level'] = 10;
// $is_member = true;
// $is_admin = 'super';
// $member = [
// 'mb_id' => $loginId,
// 'mb_name' => $_SESSION['user']['name'] ?? '관리자',
// 'mb_email' => $_SESSION['user']['email'] ?? '',
// 'mb_level' => 10,
// 'mb_nick' => '관리자',
// ];
// }
// // Descope 로그인 성공 시 (예: descope_session.php 내부)
// if (!empty($_SESSION['user']['loginIds'][0])) {
// $loginId = $_SESSION['user']['loginIds'][0];
// // g5_member 테이블에 계정이 존재한다고 가정
// $_SESSION['ss_mb_id'] = $loginId;
// $_SESSION['ss_mb_level'] = 10; // 관리자 레벨
// // 그누보드 전역 변수 보정
// $is_member = true;
// $is_admin = 'super';
// $member = [
// 'mb_id' => $loginId,
// 'mb_name' => $_SESSION['user']['name'] ?? '관리자',
// 'mb_email' => $_SESSION['user']['email'] ?? '',
// 'mb_level' => 10,
// 'mb_nick' => '관리자',
// ];
// }
// descope_session.php
// 1) 세션 시작
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (empty($_SESSION['user']['userId']) && !empty($_COOKIE['descope_login_id'])) {
$customAttributes = json_decode(base64_decode($_COOKIE['descope_custom_attributes'] ?? ''), true);
$roleNames = json_decode(base64_decode($_COOKIE['descope_role_names'] ?? ''), true);
$loginIdFromCookie = trim((string)($_COOKIE['descope_login_id'] ?? ''));
$_SESSION['user'] = [
'userId' => trim((string)($_COOKIE['descope_user_id'] ?? $loginIdFromCookie)),
'loginIds' => $loginIdFromCookie !== '' ? [$loginIdFromCookie] : [],
'name' => trim((string)($_COOKIE['descope_user_name'] ?? '')),
'email' => trim((string)($_COOKIE['descope_user_email'] ?? '')),
'phone' => trim((string)($_COOKIE['descope_user_phone'] ?? '')),
'customAttributes' => is_array($customAttributes) ? $customAttributes : [],
'roleNames' => is_array($roleNames) ? $roleNames : [],
];
}
// 2) 로그인 검사 (비로그인 차단)
// if (empty($_SESSION['user']['userId'])) {
// // 세션 없으면 바로 차단
// session_destroy();
// echo "<script>
// alert('로그인이 필요합니다.');
// // 로그인 팝업 자동 오픈 플래그 전달
// window.location.href = '/egbim/index.php?popup=login';
// </script>";
// exit;
// }
// 3) 로그인 정보 추출
$loginIds = $_SESSION['user']['loginIds'] ?? [];
$loginId = (is_array($loginIds) && !empty($loginIds)) ? $loginIds[0] : '';
$userName = $_SESSION['user']['name'] ?? '';
$userEmail = $_SESSION['user']['email'] ?? '';
// 4) 관리자/일반 사용자 구분
$ADMIN_EMAILS = [
'kjy0426@hanmaceng.co.kr',
'b24014@hanmaceng.co.kr',
'b23065@hanmaceng.co.kr',
'shyeom1@samaneng.com',
'cjy627@hanmaceng.co.kr',
'b23072@hanmaceng.co.kr',
'cozyjin@hanmaceng.co.kr',
'm24031@hanmaceng.co.kr',
'b24051@hanmaceng.co.kr',
'rmsgud1202@hanmaceng.co.kr',
'm21318@hanmaceng.co.kr',
'b25023@hanmaceng.co.kr',
'sdi9429@naver.com',
'junsuy@hanmail.net',
'ilphilo92@gmail.com'
];
// $isAdmin = in_array($loginId, $ADMIN_EMAILS, true);
$isAdmin = $loginId && in_array($loginId, $ADMIN_EMAILS, true);
// ✅ 그누보드 전역 세션 동기화
if ($loginId) {
$_SESSION['ss_mb_id'] = $loginId;
$_SESSION['ss_mb_level'] = $isAdmin ? 10 : 2;
$is_member = true;
$is_admin = $isAdmin ? 'super' : '';
$member = [
'mb_id' => $loginId,
'mb_name' => $userName ?: $loginId,
'mb_email' => $userEmail,
'mb_level' => $_SESSION['ss_mb_level'],
'mb_nick' => $userName ?: $loginId,
];
} else {
// ✅ 비회원: 로그인 세션 없음
$is_member = false;
$is_admin = '';
$member = [];
}
$loginId = $authState['loginId'];
$isAdmin = $authState['isAdmin'];
$is_member = $authState['is_member'];
$is_admin = $authState['is_admin'];
$member = $authState['member'];
?>
+27 -56
View File
@@ -1,66 +1,38 @@
<?php
// header('Content-Type: application/json');
require_once dirname(__DIR__, 4) . '/auth/common.php';
// $management_key = 'P2wON5fy1K6kyia269VpeIzYP8oP:K2ycqpjeh1voPBdxXxzB3ScZOQ6v9aiLmU2cIj70X1H8Kcoz0KWfCWmofUwAsAkJroXA8QC';
// $loginId = $_POST['loginId'] ?? '';
auth_session_start_if_needed();
header('Content-Type: application/json; charset=UTF-8');
// $url = "https://api.descope.com/v2/mgmt/user/search";
// $payload = json_encode([
// "loginId" => $loginId,
// "limit" => 1
// ]);
$loginId = trim((string) ($_POST['loginId'] ?? ''));
$sessionUser = $_SESSION['user'] ?? [];
$sessionLoginId = trim((string) ($sessionUser['loginIds'][0] ?? ''));
// $headers = [
// "Authorization: Bearer $management_key",
// "Content-Type: application/json"
// ];
if ($loginId !== '' && $sessionLoginId !== '' && strcasecmp($loginId, $sessionLoginId) === 0) {
echo json_encode(['status' => 'ok', 'user' => auth_normalize_user($sessionUser)]);
exit;
}
// $ch = curl_init($url);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
// curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// $response = curl_exec($ch);
// $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// curl_close($ch);
// if ($http_code === 200) {
// $res = json_decode($response, true);
// if (!empty($res['users'][0])) {
// // ✅ 먼저 $user에 복사
// $user = $res['users'][0];
// // ✅ 값이 없으면 테스트용 기본값 삽입
// $user['name'] = $user['name'] ?: '홍길동';
// $user['phone'] = $user['phone'] ?: '01012345678';
// $user['customAttributes']['company'] = $user['customAttributes']['company'] ?? '한맥ENG';
// $user['customAttributes']['team'] = $user['customAttributes']['team'] ?? '설계팀';
// $user['customAttributes']['employeeId'] = $user['customAttributes']['employeeId'] ?? 'HM2024';
// // ✅ 수정된 $user 사용
// echo json_encode(['status' => 'ok', 'user' => $user]);
// } else {
// echo json_encode(['status' => 'fail', 'message' => '사용자를 찾을 수 없음']);
// }
// } else {
// echo json_encode(['status' => 'fail', 'message' => 'Descope API 오류', 'code' => $http_code]);
// }
?>
<?php
header('Content-Type: application/json');
$cookieUser = auth_baron_user_from_cookies();
if ($loginId !== '' && $cookieUser !== null) {
$cookieLoginId = trim((string) ($cookieUser['loginIds'][0] ?? ''));
if ($cookieLoginId !== '' && strcasecmp($loginId, $cookieLoginId) === 0) {
echo json_encode(['status' => 'ok', 'user' => $cookieUser]);
exit;
}
}
$management_key = 'P2wON5fy1K6kyia269VpeIzYP8oP:K32l5ORmzy32OvaaPvpdZsMY3JmKQb7a3vvrl10PgjlJUGk3K7EssMH3uW5VGQSbrgtEdPj';
$loginId = $_POST['loginId'] ?? '';
$url = "https://api.descope.com/v2/mgmt/user/search";
$url = 'https://api.descope.com/v2/mgmt/user/search';
$payload = json_encode([
"loginId" => $loginId,
"limit" => 1
'loginId' => $loginId,
'limit' => 1,
]);
$headers = [
"Authorization: Bearer $management_key",
"Content-Type: application/json"
'Content-Type: application/json',
];
$ch = curl_init($url);
@@ -76,18 +48,17 @@ if ($http_code === 200) {
if (!empty($res['users'][0])) {
$user = $res['users'][0];
// ✅ 실제 값이 있으면 그대로 사용, 없으면 빈 문자열
$user['name'] = $user['name'] ?? '';
$user['phone'] = $user['phone'] ?? '';
$user['customAttributes']['company'] = $user['customAttributes']['company'] ?? '';
$user['customAttributes']['familyCompany'] = $user['customAttributes']['familyCompany'] ?? '';
$user['customAttributes']['team'] = $user['customAttributes']['team'] ?? '';
$user['customAttributes']['employeeId'] = $user['customAttributes']['employeeId'] ?? '';
$user['customAttributes']['familyUniqueKey'] = $user['customAttributes']['familyUniqueKey'] ?? '';
echo json_encode(['status' => 'ok', 'user' => $user]);
} else {
echo json_encode(['status' => 'fail', 'message' => '사용자를 찾을 수 없음']);
exit;
}
} else {
echo json_encode(['status' => 'fail', 'message' => 'Descope API 오류', 'code' => $http_code]);
}
echo json_encode(['status' => 'fail', 'message' => '사용자를 찾을 수 없음', 'code' => $http_code]);
-13
View File
@@ -355,19 +355,6 @@
</body>
<script>
$(function(){
// footer family site toggle
$('.family_btn').click(function(e){
e.stopPropagation();
$('.family_list, .family_btn').toggleClass('family_on');
});
$(document).click(function(e){
if(!$(e.target).closest('.family_wrap').length){
$('.family_list, .family_btn').removeClass('family_on');
}
});
});
// 회원 탈퇴
function member_leave() {
if (confirm("회원에서 탈퇴 하시겠습니까?"))
-13
View File
@@ -198,19 +198,6 @@
</body>
<script>
$(function(){
// footer family site toggle
$('.family_btn').click(function(e){
e.stopPropagation();
$('.family_list, .family_btn').toggleClass('family_on');
});
$(document).click(function(e){
if(!$(e.target).closest('.family_wrap').length){
$('.family_list, .family_btn').removeClass('family_on');
}
});
});
// 회원 탈퇴
function member_leave() {
if (confirm("회원에서 탈퇴 하시겠습니까?"))
-13
View File
@@ -219,19 +219,6 @@
</body>
<script>
$(function(){
// footer family site toggle
$('.family_btn').click(function(e){
e.stopPropagation();
$('.family_list, .family_btn').toggleClass('family_on');
});
$(document).click(function(e){
if(!$(e.target).closest('.family_wrap').length){
$('.family_list, .family_btn').removeClass('family_on');
}
});
});
// 회원 탈퇴
function member_leave() {
if (confirm("회원에서 탈퇴 하시겠습니까?"))
+9 -7
View File
@@ -1,9 +1,3 @@
<script type="text/javascript" src="<?php echo G5_URL ?>/js/jquery-3.6.1.min.js"></script>
<script type="text/javascript" src="<?php echo G5_URL ?>/js/jquery.mousewheel.min.js"></script>
<script type="text/javascript" src="<?php echo G5_URL ?>/js/common.js"></script>
<script type="text/javascript" src="<?php echo G5_URL ?>/js/include.js"></script>
<script type="text/javascript" src="<?php echo G5_URL ?>/js/popup.js?v=20260723"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<!--popup_wrap-->
@@ -57,8 +51,12 @@
<div class="join_btn_wrap">
<button type="submit" id="btn_login">Login</button>
</div>
<div class="join_btn_wrap" style="margin-top:10px;">
<a href="/auth/baron_login?site=eng&amp;return_url=/eng/bbs/descope_qa_list.php" style="display:block; width:100%; text-align:center; padding:14px 16px; border:1px solid #0f3a2f; border-radius:10px; color:#0f3a2f; font-weight:700;">BARON-SSO Login</a>
</div>
<p style="margin-top:10px; font-size:16px; font-weight:700; color:#c62828; line-height:1.6; text-align:center;">eg-bim 1.5.1 버전 이상 사용자는 baron-sso로 로그인해야 합니다.</p>
<div class="btn_go">
<div class="go_signup"><a href="javascript:agreement();"><span>Sign up</span><i class="arrow_r"></i></a></div>
<div class="go_signup"><a href="#" class="signup-disabled-link" aria-disabled="true"><span>Sign up</span><i class="arrow_r"></i></a></div>
<div class="go_find"><a href="javascript:search();"><span>Reset Password</span><i class="arrow_r"></i></a></div>
</div>
</form>
@@ -132,6 +130,10 @@ $(document).ready(function () {
e.preventDefault(); // 기본 제출 막기
$('#btn_login').click(); // 버튼 클릭 이벤트 재사용
});
$('.signup-disabled-link').on('click', function (e) {
e.preventDefault();
});
});
document.addEventListener("DOMContentLoaded", () => {
-13
View File
@@ -151,19 +151,6 @@ include_once __DIR__ . '/asset_urls.php';
</script>
</body>
<script>
$(function(){
// footer family site toggle
$('.family_btn').click(function(e){
e.stopPropagation();
$('.family_list, .family_btn').toggleClass('family_on');
});
$(document).click(function(e){
if(!$(e.target).closest('.family_wrap').length){
$('.family_list, .family_btn').removeClass('family_on');
}
});
});
// 회원 탈퇴
function member_leave() {
if (confirm("회원에서 탈퇴 하시겠습니까?"))
+82 -3
View File
@@ -55,7 +55,7 @@ $download_url = "https://release-download.hmac.kr/eg-bim/{$version}/setup_eg-bim
<a href="javascript:descopeLogout();">Logout</a>
</li>
<li id="my_join" class="my_join">
<a href="javascript:agreement();">Sign up</a>
<a href="#" class="signup-disabled-link" aria-disabled="true">Sign up</a>
</li>
<li id="my_login" class="my_login">
<a href="javascript:login();">Login</a>
@@ -94,9 +94,84 @@ $download_url = "https://release-download.hmac.kr/eg-bim/{$version}/setup_eg-bim
// e.preventDefault(); // 링크 이동 막기
// alert('다운로드 기능은 준비중입니다.');
// });
</script>
<script>
(function () {
function getCookieValue(name) {
const prefix = name + '=';
const parts = document.cookie.split(';');
for (let i = 0; i < parts.length; i += 1) {
const part = parts[i].trim();
if (part.indexOf(prefix) === 0) {
return part.substring(prefix.length);
}
}
return '';
}
function decodeBase64Json(value) {
if (!value) return null;
try {
const binary = window.atob(value);
const bytes = Array.prototype.map.call(binary, function (char) {
return '%' + ('00' + char.charCodeAt(0).toString(16)).slice(-2);
}).join('');
return JSON.parse(decodeURIComponent(bytes));
} catch (error) {
return null;
}
}
function setStoredValue(key, value) {
if (typeof value === 'string' && value !== '') {
sessionStorage.setItem(key, value);
}
}
function restoreClientAuthSessionFromCookies() {
const baronUser = decodeBase64Json(getCookieValue('baron_user'));
if (baronUser && Array.isArray(baronUser.loginIds) && baronUser.loginIds[0]) {
const customAttributes = baronUser.customAttributes || {};
const roleNames = Array.isArray(baronUser.roleNames) ? baronUser.roleNames : [];
setStoredValue('authProvider', 'baron');
setStoredValue('loginId', baronUser.loginIds[0] || '');
setStoredValue('descopeUserId', baronUser.userId || '');
setStoredValue('userName', baronUser.name || '');
setStoredValue('phone', baronUser.phone || '');
setStoredValue('company', customAttributes.company || '');
setStoredValue('familyCompany', customAttributes.familyCompany || '');
setStoredValue('team', customAttributes.team || '');
setStoredValue('position', customAttributes.position || '');
setStoredValue('familyUniqueKey', customAttributes.familyUniqueKey || '');
setStoredValue('userRole', roleNames[0] || '');
setStoredValue('sessionJwt', sessionStorage.getItem('sessionJwt') || 'baron.session.marker');
return;
}
const descopeLoginId = getCookieValue('descope_login_id');
if (descopeLoginId && !sessionStorage.getItem('loginId')) {
const customAttributes = decodeBase64Json(getCookieValue('descope_custom_attributes')) || {};
const roleNames = decodeBase64Json(getCookieValue('descope_role_names')) || [];
setStoredValue('authProvider', sessionStorage.getItem('authProvider') || 'descope');
setStoredValue('loginId', descopeLoginId);
setStoredValue('descopeUserId', getCookieValue('descope_user_id'));
setStoredValue('userName', getCookieValue('descope_user_name'));
setStoredValue('phone', getCookieValue('descope_user_phone'));
setStoredValue('company', customAttributes.company || '');
setStoredValue('familyCompany', customAttributes.familyCompany || '');
setStoredValue('team', customAttributes.team || '');
setStoredValue('position', customAttributes.position || '');
setStoredValue('familyUniqueKey', customAttributes.familyUniqueKey || '');
setStoredValue('userRole', Array.isArray(roleNames) ? (roleNames[0] || '') : '');
}
}
restoreClientAuthSessionFromCookies();
})();
(function () {
const ADMIN_ICON_IDS = [
'b24014@hanmaceng.co.kr',
@@ -179,6 +254,10 @@ $download_url = "https://release-download.hmac.kr/eg-bim/{$version}/setup_eg-bim
}, 50);
});
$(document).on('click', '.signup-disabled-link', function (e) {
e.preventDefault();
});
// 혹시 로그인 팝업을 다른 곳에서 열어도 배너가 필요하면, 팝업 열릴 때 한 번 더 시도
$(document).on('show-login-popup', function () {
injectBanner();
-13
View File
@@ -312,19 +312,6 @@
</body>
<script>
$(function(){
// footer family site toggle
$('.family_btn').click(function(e){
e.stopPropagation();
$('.family_list, .family_btn').toggleClass('family_on');
});
$(document).click(function(e){
if(!$(e.target).closest('.family_wrap').length){
$('.family_list, .family_btn').removeClass('family_on');
}
});
});
// 회원 탈퇴
function member_leave() {
if (confirm("회원에서 탈퇴 하시겠습니까?"))
-3
View File
@@ -17,9 +17,6 @@ if (!isset($register_action_url)) {
<link rel="stylesheet" href="../css/style.css" />
<script src="../js/jquery-3.6.1.min.js"></script> -->
<!-- </head> -->
<script src="<?php echo G5_URL ?>/js/common.js"></script>
<script src="<?php echo G5_URL ?>/js/popup.js?v=20260723"></script>
<!-- 회원가입약관 동의 시작 { -->
<!-- <body>
<div class="register"> -->
-13
View File
@@ -256,19 +256,6 @@
</body>
<script>
$(function(){
// footer family site toggle
$('.family_btn').click(function(e){
e.stopPropagation();
$('.family_list, .family_btn').toggleClass('family_on');
});
$(document).click(function(e){
if(!$(e.target).closest('.family_wrap').length){
$('.family_list, .family_btn').removeClass('family_on');
}
});
});
// 회원 탈퇴
function member_leave() {
if (confirm("회원에서 탈퇴 하시겠습니까?"))