Here, we will learn about how we can protect the routes in our Vue.js application. It is very useful for any application as there are pages which can be accessed only when we are logged in the application. I have used the Vuexy theme for the demo so the css and assets will not be found, it just for your reference.
Protecting routes:
Step 1: Install the following packages in vue.js:
npm i vue-router
Step 2: Open router.js and add the following in it:
import Vue from 'vue' import VueRouter from 'vue-router' import { isUserLoggedIn } from '@/auth/utils' Vue.use(VueRouter) const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, scrollBehavior() { return { x: 0, y: 0 } }, routes: [ { path: '/', name: 'home', component: () => import('@/views/Home.vue'), meta: { pageTitle: 'Home', breadcrumb: [ { text: 'Home', active: true, }, ], }, }, { path: '/blank-page', name: 'blank-page', component: () => import('@/views/BlankPage.vue'), meta: { pageTitle: 'Department', breadcrumb: [ { text: 'Department', active: true, }, ], }, }, { path: '/login', name: 'login', component: () => import('@/views/Login.vue'), meta: { layout: 'full', }, }, { path: '/error-404', name: 'error-404', component: () => import('@/views/error/Error404.vue'), meta: { layout: 'full', }, }, { path: '*', redirect: 'error-404', }, ], }) router.afterEach(() => { const appLoading = document.getElementById('loading-bg') if (appLoading) { appLoading.style.display = 'none' } }) router.beforeEach((to, from, next) => { const { canActivate } = to.meta if (canActivate) { const isLoggedIn = isUserLoggedIn() if (!isLoggedIn) { next({ path: '/', name: 'login' }) // query: { returnUrl: to.path } } } next() }) export default router
Step 3: Open utils.js and add the following in it:
export const isUserLoggedIn = () => { return localStorage.getItem(useJwt.jwtConfig.storageTokenKeyName) } export const getUserData = () => JSON.parse(localStorage.getItem('userData'))
Step 4: Open login.Vue and add the following in it:
<template> <div class="auth-wrapper auth-v2"> <b-row class="auth-inner m-0"> <!-- Brand logo--> <b-link class="brand-logo"> <h2 class="brand-text text-primary ml-1"> Vuexy </h2> </b-link> <!-- /Brand logo--> <!-- Left Text--> <b-col lg="8" class="d-none d-lg-flex align-items-center p-5" > <div class="w-100 d-lg-flex align-items-center justify-content-center px-5"> <b-img fluid :src="imgUrl" alt="Login V2" /> </div> </b-col> <b-col lg="4" class="d-flex align-items-center auth-bg px-2 p-lg-5" > <b-col sm="8" md="6" lg="12" class="px-xl-2 mx-auto" > <b-card-title title-tag="h2" class="font-weight-bold mb-1" > Welcome to Vuexy! ???? </b-card-title> <b-card-text class="mb-2"> Please sign-in to your account and start the adventure </b-card-text> <!-- form --> <validation-observer ref="loginValidation"> <b-form class="auth-login-form mt-2" @submit.prevent > <!-- email --> <b-form-group label="Email" label-for="login-email" > <validation-provider #default="{ errors }" name="Email" rules="required|email" > <b-form-input id="login-email" v-model="loginInfo.email" :state="errors.length > 0 ? false : null" name="login-email" placeholder="john@example.com" /> <small class="text-danger">{{ errors[0] }}</small> </validation-provider> </b-form-group> <!-- forgot password --> <b-form-group> <div class="d-flex justify-content-between"> <label for="login-password">Password</label> <b-link :to="{ name: 'forget-password-page' }"> <small>Forgot Password?</small> </b-link> </div> <validation-provider #default="{ errors }" name="Password" rules="required" > <b-input-group class="input-group-merge" :class="errors.length > 0 ? 'is-invalid' : null" > <b-form-input id="login-password" v-model="loginInfo.password" :state="errors.length > 0 ? false : null" class="form-control-merge" :type="passwordFieldType" name="login-password" placeholder="············" /> <b-input-group-append is-text> <feather-icon class="cursor-pointer" :icon="passwordToggleIcon" @click="togglePasswordVisibility" /> </b-input-group-append> </b-input-group> <small class="text-danger">{{ errors[0] }}</small> </validation-provider> </b-form-group> <!-- submit buttons --> <b-button type="submit" variant="primary" block @click="authentication" > Sign in </b-button> </b-form> </validation-observer> <b-card-text class="text-center mt-2"> <span>Don't have an account? </span> <b-link :to="{ name: 'registration' }"> <span>Sign Up</span> </b-link> </b-card-text> </b-col> </b-col> <!-- /Login--> </b-row> </div> </template> <script> /* eslint-disable */ import { ValidationProvider, ValidationObserver } from 'vee-validate' import { BRow, BCol, BLink, BFormGroup, BFormInput, BInputGroupAppend, BInputGroup, BCardText, BCardTitle, BImg, BForm, BButton } from 'bootstrap-vue' import { togglePasswordVisibility } from '@core/mixins/ui/forms' import store from '@/store/index' import useJwt from '@/auth/jwt/useJwt' import ToastificationContent from '@core/components/toastification/ToastificationContent.vue' export default { components: { BRow, BCol, BLink, BFormGroup, BFormInput, BInputGroupAppend, BInputGroup, BCardText, BCardTitle, BImg, BForm, BButton, ValidationProvider, ValidationObserver, }, mixins: [togglePasswordVisibility], data() { return { status: '', loginInfo: {}, data: JSON.parse(localStorage.getItem('userData')), sideImg: require('@/assets/images/pages/login-v2.svg'), // validation rulesimport store from '@/store/index' required, email, responseData: {}, } }, mounted() { this.checkLogoin() }, computed: { passwordToggleIcon() { return this.passwordFieldType === 'password' ? 'EyeIcon' : 'EyeOffIcon' }, imgUrl() { if (store.state.appConfig.layout.skin === 'dark') { // eslint-disable-next-line vue/no-side-effects-in-computed-properties this.sideImg = require('@/assets/images/pages/login-v2-dark.svg') return this.sideImg } return this.sideImg }, }, methods: { authentication() { var app = this this.$refs.loginValidation.validate().then(success => { if (success) { useJwt .login(this.loginInfo) .then(res => { this.responseData = res.data.data if (this.responseData.roleId === 1) { const userData = JSON.stringify(this.responseData) window.localStorage.setItem('userData', userData) app.$store.state.isLoggedIn = true useJwt.setToken(this.responseData.token) useJwt.setRefreshToken(this.responseData.token) this.$router.push({ name: 'home' }) } }) .catch(() => { this.$toast({ component: ToastificationContent, props: { title: 'Failed to Login', icon: 'CloseIcon', variant: 'danger', }, }) }) } }) }, checkLogoin() { if (this.data != null) this.$router.push({ name: 'home', path: '/' }) }, }, } </script> <style lang="scss"> @import '@core/scss/vue/pages/page-auth.scss'; </style>
Code in action: