Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions healthtartFront/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion healthtartFront/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.7.7",
"axios": "^1.8.4",
"chart.js": "^4.4.9",
"jwt-decode": "^4.0.0",
"vue": "^3.5.11",
"vue-router": "^4.0.13"
Expand Down
4 changes: 2 additions & 2 deletions healthtartFront/src/components/users/FindEmailForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
document.querySelector('.verification-btn').disabled = true;
}
} catch (error) {
phoneErrorMessage = '인증번호 발송에 실패했습니다. 다시 시도해주세요.';
phoneErrorMessage.value = '인증번호 발송에 실패했습니다. 다시 시도해주세요.';
console.error('SMS 전송 오류:', error); // 로그 추가
}
};
Expand Down Expand Up @@ -231,7 +231,7 @@ label {
}

#verification-code {
/* margin-bottom: 25px; */
margin-bottom: 25px;
}

.form-group {
Expand Down
38 changes: 35 additions & 3 deletions healthtartFront/src/components/users/LoginForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,41 @@ const goToFindEmail = () => {
router.push('/users/findemail');
}

const kakaoLogin = () => {
window.location.href = 'http://localhost:8080/oauth2/authorization/kakao';
};
// const kakaoLogin = () => {
// window.location.href = 'http://localhost:8080/oauth2/authorization/kakao';
// };

// pkce를 위한 codeVerifier 생성
const generateCodeVerifier = () => {
const array = new Uint32Array(56);
window.crypto.getRandomValues(array);
return Array.from(array, dec => ('0' + dec.toString(16)).slice(-2)).join('');
};

// pkce를 위한 codeChallenge 생성
const generateCodeChallenge = async (verifier) => {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await crypto.subtle.digest('SHA-256', data);
return btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
};

const kakaoLogin = async () => {
const codeVerifier = generateCodeVerifier();
sessionStorage.setItem('code_verifier', codeVerifier);

const codeChallenge = await generateCodeChallenge(codeVerifier);

const clientId = '6cbd43ba1b1fa2803c31d42c0b49c27f'; // 카카오 REST API 키
const redirectUri = 'http://localhost:5173/users/oauth/callback'; // 프론트 콜백 주소
const kakaoAuthUrl =
`https://kauth.kakao.com/oauth/authorize?
response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
window.location.href = kakaoAuthUrl;
};


const googleLogin = () => {
Expand Down
2 changes: 2 additions & 0 deletions healthtartFront/src/router/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import LoginPage from "@/views/users/LoginPage.vue";
import AddInfoPage from "../views/users/AddInfoPage.vue";
import ResetPasswordPage from "../views/users/ResetPasswordPage.vue";
import FindEmailPage from "../views/users/FindEmailPage.vue";
import OAuthKakaoCallback from "../views/users/OAuthKakaoCallback.vue";

const UserRoutes = [
{ path: "/mypage", component: MyPage, meta: { requiresAuth: true } },
Expand All @@ -12,6 +13,7 @@ const UserRoutes = [
{ path: "/users/addinfo", component: AddInfoPage},
{ path: "/users/password", component: ResetPasswordPage},
{ path: "/users/findemail", component: FindEmailPage},
{ path: "/users/oauth/callback", component: OAuthKakaoCallback}
];

export default UserRoutes;
13 changes: 4 additions & 9 deletions healthtartFront/src/views/MainPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,17 @@ onMounted(() => {
blueWave.className = 'blue-wave';
document.querySelector('.app').appendChild(blueWave);

// URL에서 토큰 파라미터 확인
const token = route.query.token;

const token = localStorage.getItem('token');

if (token) {
// 토큰을 로컬 스토리지에 저장
localStorage.setItem('token', token);

// jwt-decode를 사용해 닉네임 추출
const decodedToken = jwtDecode(token);
const userNickname = decodedToken.nickname; // 토큰에서 nickname 추출
const userNickname = decodedToken.nickname;

// 로그인 상태 업데이트
loginState.state.isLoggedIn = true;
loginState.state.userNickname = userNickname; // 추출한 닉네임을 loginState에 저장
loginState.state.userNickname = userNickname;

// 토큰을 제거한 URL로 리다이렉트
router.replace('/');
}
});
Expand Down
43 changes: 43 additions & 0 deletions healthtartFront/src/views/users/OAuthKakaoCallback.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<div>로그인 처리 중입니다...</div>
</template>

<script setup>
import { onMounted } from 'vue';
import axios from 'axios';
import { useRouter } from 'vue-router';

const router = useRouter();

onMounted(async () => {
const query = new URLSearchParams(window.location.search);
const code = query.get('code');
const codeVerifier = sessionStorage.getItem('code_verifier'); // PKCE

if (code && codeVerifier) {
try {
const response = await axios.post('http://localhost:8080/api/oauth/kakao', {
code,
codeVerifier
},{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
console.log(response)
const jwt = response.data.token;

// localStorage에 저장
localStorage.setItem('token', jwt);
sessionStorage.removeItem('code_verifier');
router.push('/'); // 메인 페이지로 이동

} catch (error) {
console.error('로그인 실패', error);
router.push('/login');
}
}
});
</script>