Protecting Routes with Middleware in Vue Applications
When building Single Page Applications (SPAs), it’s essential to protect certain routes from unauthorized access. In this article, we’ll explore how to implement a middleware pipeline in a Vue application using Vue-Router.
What is a Middleware Pipeline?
A middleware pipeline is a stack of functions that run in parallel, allowing you to chain multiple middlewares together. This approach enables you to protect routes with multiple conditions, such as authentication and subscription status.
Getting Started
To demonstrate the concept, let’s create a simple Vue application with three components: Login, Dashboard, and Movies. We’ll use Vue-Router to manage client-side routing and Vuex for state management.
Creating Components
Create the following files in the src/components
directory:
Login.vue
Dashboard.vue
Movies.vue
Creating the Store
Create a store.js
file in the src
directory to manage the application state:
“`javascript
import Vuex from ‘vuex’
const store = new Vuex.Store({
state: {
user: {
loggedIn: false,
isSubscribed: false
}
},
getters: {
getUser(state) {
return state.user
}
}
})
export default store
“`
Defining Routes
Define the routes and associate them with the corresponding middlewares:
“`javascript
import Vue from ‘vue’
import VueRouter from ‘vue-router’
import store from ‘./store’
Vue.use(VueRouter)
const routes = [
{
path: ‘/login’,
component: Login,
meta: {
middleware: [‘guest’]
}
},
{
path: ‘/dashboard’,
component: Dashboard,
meta: {
middleware: [‘auth’]
}
},
{
path: ‘/dashboard/movies’,
component: Movies,
meta: {
middleware: [‘auth’, ‘isSubscribed’]
}
}
]
const router = new VueRouter({
routes
})
“`
Creating Middlewares
Create the following middleware files in the src/router/middleware
directory:
guest.js
auth.js
isSubscribed.js
Implementing Middlewares
Implement the middleware logic in each file:
“`javascript
// guest.js
import store from ‘../../store’
export default async (context) => {
if (store.getters.getUser.loggedIn) {
context.redirect(‘/dashboard’)
}
}
// auth.js
import store from ‘../../store’
export default async (context) => {
if (!store.getters.getUser.loggedIn) {
context.redirect(‘/login’)
}
}
// isSubscribed.js
import store from ‘../../store’
export default async (context) => {
if (!store.getters.getUser.isSubscribed) {
context.redirect(‘/dashboard’)
}
}
“`
Running Middlewares
Use the beforeEach
hook to run the middlewares:
javascript
router.beforeEach((to, from, next) => {
const middleware = to.meta.middleware
if (middleware) {
middleware.forEach((middleware) => {
middleware({ to, from, next })
})
} else {
next()
}
})
Creating a Middleware Pipeline
Create a middlewarePipeline.js
file to manage the middleware pipeline:
“`javascript
import store from ‘../../store’
export default async (context, middleware, index) => {
const nextMiddleware = middleware[index]
if (nextMiddleware) {
await nextMiddleware(context)
await middlewarePipeline(context, middleware, index + 1)
}
}
“`
Bringing it all Together
Update the beforeEach
hook to use the middleware pipeline:
javascript
router.beforeEach((to, from, next) => {
const middleware = to.meta.middleware
if (middleware) {
middlewarePipeline({ to, from, next }, middleware, 0)
} else {
next()
}
})
With this implementation, you can now protect your routes with multiple middlewares, ensuring that only authorized users can access specific pages.