Vue-Login-Frontend1

dyeon-dev·2023년 11월 25일
0
post-thumbnail

JWT로 인증하는 로그인/회원가입 서비스를 기존 프로젝트에 추가할 것이다.
JWT를 조금 더 안전하게 저장하는 방법으로 regen token을 사용하여 토큰이 만료되면 사용자에게 바로 연장 요청을 하는 기능을 구현하는 과정을 기록한다.

1. Pinia Store 생성

store/userStore.ts

id와 token 값을 관리할 pinia store를 만들어준다.

  • 로그인 시 id를 저장할 setUsername 함수를 작성한다.
  • 로그아웃을 관리할 clearUsername 함수를 작성하여 저장해 놓은 id 정보를 없애준다. 외부에서 Store를 참조하여 clearUsername을 실행 해 주면 저장해 놓은 id 정보를 없앨 수 있다.
  • 토큰은 regen token으로 관리할 것이기 때문에 token 한개의 변수를 설정해둔다.
import { defineStore } from 'pinia';

export const useUserStore = defineStore({
  id: 'main',
  state: () => ({
    id: '',
    token: '',
  }),
  getters: {
    isLogin: (state) => {
      return state.id !== '';
    },
  },
  actions: {
    setUsername(id: string) {
      this.id = id;
    },
    clearUsername() {
      this.id = '';
    },
    setToken(token: string) {
      this.token = token;
    }
  },
});

2. 로그인 폼 작성

그 다음, LoginView.vue 파일을 만들고 로그인 폼을 간단하게 만든다. 아이디와 비밀번호를 입력 받는다.

<template>
    <div class="column items-center">
        <div class="col q-pa-lg">
            <q-img src="/src/assets/login.png" style="width: 300px; height: 50px;" />
        </div>
        <div class="col" style="max-width: 400px; margin-top: -100px;">
            <h6><b>로그인</b></h6>
            <q-form @submit="onSubmit" class="q-gutter-md">
                <q-input filled v-model="id" label="아이디 *" lazy-rules
                    :rules="[(val: string | any[]) => val && val.length > 0 || '아이디를 입력해주세요']" />
								<q-input filled v-model="pw" label="비밀번호 *" lazy-rules 
		                :rules="[(val: string | any[]) => val && val.length > 0 || '비밀번호를 입력해주세요']"/>                <div>
                    <q-btn label="login" type="submit" color="primary" class="q-ml-sm" />
                    <q-btn label="signup" to="/Signup" color="secondary" class="q-ml-lg" />
                </div>
            </q-form>
        </div>
    </div>
</template>

3. Axios 연결

백엔드 서버 구축해 놓은 부분을 연결해보자. 그리고 로그인 시 받아온 id와 백엔드에서 받은 token 값을 store에 저장한다.

<script setup lang="ts">
import { useQuasar } from 'quasar'
import { ref } from 'vue'
import axios from 'axios';
import { useRouter } from 'vue-router';
import { useUserStore } from "../store/userStore";

const $q = useQuasar()
const router = useRouter();
const userStore = useUserStore();

const id = ref<string>('');
const pw = ref<string>('');

const onSubmit = async () => {
    try {
        const userData = {
            id: id.value,
            pw: pw.value,
        };

        const { data } = await axios.post("/login", userData);
        console.log(data);
        userStore.setUsername(userData.id);
        userStore.setToken(data.token);

        $q.notify({
            color: 'green-4',
            textColor: 'white',
            icon: 'cloud_done',
            message: '로그인 성공'
        })
        router.push({ path: '/Home' });
    }
    catch (error) {
        console.log(error);
        $q.notify({
            color: 'red-5',
            textColor: 'white',
            icon: 'warning',
            message: '아이디와 비밀번호가 일치하지 않습니다'
        })
    } finally {
        id.value = '';
        pw.value = '';
    }
};
</script>

4. 사용자 정보 출력

상단바 Layout에서 사용자 활동을 관리하도록 할 것이다.

  • 로그인 여부에 따라 노출 되는 정보가 달라지게 한다.
  • logoutUser 함수가 store의 clearUsername을 참조하고, /login 페이지로 돌아가게 해 준다.
<template v-if="isUserLogin()">
          <div class="q-gutter-x-md">
            <span> {{ userStore.id }} 님 환영합니다!</span>
            <q-btn color="secondary"><a href="javascript:;" @click="logoutUser"
                style="text-decoration: none; color: white;">Logout</a></q-btn>
          </div>
</template>

<script setup lang="ts">
import { useUserStore } from "../store/userStore";
import { useRouter } from 'vue-router';

const router = useRouter();
const userStore = useUserStore();
const logoutUser = () => {
  userStore.clearUsername();
  router.push({ path: '/Login' });
}

const isUserLogin = () => {
  return userStore.isLogin;
};
</script>

여기까지 완료하면 백엔드에서 임시로 구축해둔 아이디와 비밀번호로 로그인이 가능하다.

다음은 JWT 핸들링하여 토큰 만료 시간을 계산한 후 알림창을 띄워주고 regen token을 갱신시키도록 하겠다.

profile
https://dyeon-dev.vercel.app/ ⬅️ 블로그 이전

0개의 댓글