로그인 방식
세션 로그인 방식
- 백엔드 서버에 로그인했다는 정보를 저장
토큰 로그인 방식
- 클라이언트에 로그인했다는 정보를 저장
로그인 여부 확인 방법
1. 서버로 쿠키를 주고 받는다. (백엔드를 통해서 확인)
- 장점: 클라이언트가 조작하기 어려움
- 단점: 백엔드 부하 증가
2. 웹 브라우저에서 HttpOnly가 아닌 일반 쿠키 또는 스토리지에 로그인 했다는 정보를 저장한다.
- 장점: 백엔드에게 물어보지 않아도 바로 로그인 여부 확인 가능, 백엔드 부하 감소
- 단점: 클라이언트가 조작하기 어려움
Vue Router 접근 권한 설정
라우터 파일을 통해 접근 권한을 설정한다.
접근 권한을 설정하고 싶은 경로에 beforeEnter: 함수 를 넣어준다.
{ path: "/a", component: A, beforeEnter: checkLogin }
router/index.js
import { createRouter, createWebHistory } from "vue-router";
import A from "../components/A.vue";
import B from "../components/B.vue";
import Login from "../components/Login.vue";
const checkLogin = (from, to, next) => {
// 로그인을 확인하는 코드 실행
if (false) {
return next();
}
next("/user/login");
};
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/a", component: A, beforeEnter: checkLogin },
{ path: "/b", component: B },
{ path: "/user/login", component: Login },
],
});
export default router;
App.vue
<script setup>
</script>
<template>
<ul>
<li>
<router-link to="/a">A</router-link>
</li>
<li>
<router-link to="/b">B</router-link>
</li>
</ul>
<router-view></router-view>
</template>
<style scoped></style>
/b는 접근 권한 설정이 안 되어 있기 때문에 아무나 접근할 수 있다.
A로 가려고 할 때 접근이 되지 않고 /user/login 경로로 강제로 이동한다.
Pinia Store 활용해서 로그인 기능 구현 (새로고침 시 초기화)
아래의 방법은 로그인 확인 방법 중 서버로 쿠키를 주고 받는 방법을 사용한 것이다.
useUserStore.js
isLogin이라는 변수를 만들어서 login이 될 때 `true`로 바꿔준다.
`loginCheck`는 ATOKEN 쿠키가 있으면 isSuccess: true라는 데이터가 온다.
import axios from "axios";
import { defineStore } from "pinia";
export const useUserStore = defineStore("user", {
state: () => ({ isLogin: false }),
actions: {
async signUp(signUpData) {
const response = await axios.post("/api/user/signup", signUpData);
return response.data;
},
async login(loginData) {
const response = await axios.post("/api/login", loginData);
if (response.data.isLogin) {
this.isLogin = true;
}
return response;
},
async loginCheck() {
const response = await axios.get("/api/user/auth/check", {
withCredentials: true,
});
if (response.data.isSuccess) {
this.isLogin = true;
}
return response.data;
},
},
});
router/index.js
/a 경로로 이동할 때 checkLogin 함수를 실행해서 userStore의 loginCheck 함수로 쿠키 토큰이 있는지 확인한다.
import { createRouter, createWebHistory } from "vue-router";
import A from "../components/A.vue";
import B from "../components/B.vue";
import Login from "../components/Login.vue";
import { useUserStore } from "../stores/useUserStore";
import Logout from "../components/Logout.vue";
const checkLogin = async (from, to, next) => {
//로그인을 확인하는 코드 실행
const userStore = useUserStore();
await userStore.loginCheck();
if (userStore.isLogin) {
return next();
}
next("/user/login");
};
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/a", component: A, beforeEnter: checkLogin },
{ path: "/b", component: B },
{ path: "/user/login", component: Login },
{ path: "/user/logout", component: Logout },
],
});
export default router;
Login.vue
로그인 버튼을 눌렀을 때 userStore의 login 함수를 실행한다.
<script setup>
import { ref } from "vue";
import { useUserStore } from "../stores/useUserStore";
import router from "../router";
const loginData = ref({
username: "",
password: "",
});
const userStore = useUserStore();
const login = async () => {
const result = await userStore.login(loginData.value);
console.log(result);
};
</script>
<template>
<div>
<p>이메일</p>
<input type="email" v-model="loginData.username" />
<p>비밀번호</p>
<input type="password" v-model="loginData.password" />
<button @click="login">로그인</button>
</div>
</template>
<style scoped>
/* style 생략 */
</style>
App.vue
<script setup>
import { useUserStore } from "./stores/useUserStore";
const userStore = useUserStore();
</script>
<template>
<ul>
<li v-if="userStore.isLogin">
<router-link to="/user/logout">Logout</router-link>
</li>
<li v-else>
<router-link to="/user/login">Login</router-link>
</li>
<li>
<router-link to="/a">A</router-link>
</li>
<li>
<router-link to="/b">B</router-link>
</li>
</ul>
<router-view></router-view>
</template>
<style scoped></style>
로그인을 하면 개발자 도구 - 애플리케이션 - 쿠키 탭에 ATOKEN으로 토큰이 들어와있다.
이렇게 하면 로그인 했을 때 쿠키는 들어오지만, 새로고침 하면 다시 Login이 풀리는 것을 확인할 수 있다.
맨 위에 Logout 버튼이 새로고침 하면 다시 Login으로 바뀐다.
이러한 일이 발생하는 이유는 useUserStore 때문이다.
store를 사용하는 컴포넌트가 화면에 보여지면서 사용이 될 때, 컴포넌트 객체가 생성이 되면서 안에서 쓰는 store 객체도 새로 만들어진다.
객체가 없어졌다가 새로 생기면 안에 있던 변수가 초기값으로 초기화된다.
-> 컴포넌트가 사용이 될 때마다 변수값이 계속 초기화된다.
=> 페이지를 이동해도 변수값을 유지하는 기능이 필요하다. (추가 라이브러리 pinia-plugin-persistedstate 설치)
pinia-plugin-persistedstate
설치
npm instrall pinia-plugin-persistedstate
사용
main.js에 piniaPersistedstate를 추가해준다.
main.js
import piniaPersistedstate from "pinia-plugin-persistedstate";
const pinia = createPinia();
pinia.use(piniaPersistedstate);
// app 부분 생략
store 파일에 persist를 추가해준다.
보통 로그인은 세션 스토리지를 사용하기 때문에 세션 스토리지에 저장해준다.
persist: {
storage: sessionStorage,
},
useUserStore.js
persist를 추가해준다.
import axios from "axios";
import { defineStore } from "pinia";
export const useUserStore = defineStore("user", {
state: () => ({ isLogin: false }),
persist: {
storage: sessionStorage,
},
actions: {
async signUp(signUpData) {
const response = await axios.post("/api/user/signup", signUpData);
return response.data;
},
async login(loginData) {
const response = await axios.post("/api/login", loginData);
if (response.data.isLogin) {
this.isLogin = true;
}
return response;
},
async loginCheck() {
const response = await axios.get("/api/user/auth/check", {
withCredentials: true,
});
if (response.data.isSuccess) {
this.isLogin = true;
}
return response.data;
},
},
});
개발자 도구 - 애플리케이션 - 세션 저장소 에 값이 들어와있다.
'FE > Vue.js' 카테고리의 다른 글
[Vue] Pinia 설치 / Store 사용 (loading, axios) (0) | 2024.12.23 |
---|---|
[Vue] 컴포넌트 간 데이터 주고받기 (Props, Emit) (0) | 2024.12.23 |
[Vue] 데이터 바인딩 (ref, reactive) / 조건문, 반복문 (v-if, v-for) / v-model (0) | 2024.12.20 |
[Vue] Vue Router란? / Vue Router 사용 (router-link, useRouter) (1) | 2024.12.20 |
[Vue] VSCode에서 Vue.js 템플릿 설정 (Vue.js Snippet) (0) | 2024.12.20 |