Vue 登录验证练习

Vue 登录验证练习

最近公司在做一个后台管理系统,顺便在这里记录一下登录权限验证的过程, 以便以后使用

工具:

vue全家桶(Vuex,Vue Router,Vue) + axios;

思路:

在登录页面登录成功后后台返回一个 token(该 token 用于验证用户登录状态),将 token 保存在 cookies 和 store 里。之后每次在向后端发送请求时在 header 里添加一个 token 字段用于验证用户状态,如果 token 失效,接口返回状态码 300, 使用 axios 创建一个拦截器,如果返回接口的状态码为300,将清除cookies 和 store 里的 token 值并转到登录页面。
每次刷新页面后 store 里的数据会丢失, 所以将判断 cookie 里是否存在 token ,如果存在, 将其赋予到 store 中保存

开始撸代码

创建一个 axios 拦截器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// request.js
import axios from 'axios';
import auth from './auth';
import store from './store';
import router from './router';

const request = axios.create({ //创建一个拦截器
    baseURL: '',
    timeout: 5000
});

request.interceptors.request.use(
    config => {
        if (store.state.token) {
            config.headers['token'] = auth.getToken().token; // 在头部设置一个 token 字段来验证用户状态
        }
        return config;
    },
    err => {
        return Promise.reject(err);
    }
);

request.interceptors.response.use(
    response => {
        if (response.data.code === 300) {
            // 如果 code 为 300 表示token已失效, 需要重新登录
            store.commit('logout'); // 删除token
            router.replace({ // 跳转到登录页,并记录下当前页面的路由路径
                path: '/login',
                query: {
                    redirect: router.currentRoute.path
                }
            });
        }
        return response;
    },
    error => {
        console.log(error)
        return Promise.reject(error);
    }
);

export default request;

创建一个 auth.js 用于存放操作 token 的函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// auth.js
import Cookies from 'js-cookie';

const TokenKey = 'Admin-Token'; // 存储在cookies中的名字

export default {
    getToken() {
        //获取token
        return Cookies.get(TokenKey);
    },
    setToken(token) {
        //设置token
        return Cookies.set(TokenKey, token);
    },
    removeToken() {
        //删除token
        return Cookies.remove(TokenKey);
    }
};

创建一个 store.js 用于存放vuex的一些配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// store.js
import Vue from 'vue';
import Vuex from 'vuex';

import auth from './auth';

Vue.use(Vuex);

export default new Vuex.Store({
    state: {
        user: {},
        token: null,
        title: ''
    },
    mutations: {
        login: (state, data) => {
            auth.setToken(data);
            state.token = data;
        },
        logout: state => {
            auth.removeToken();
            state.token = null;
        }
    },
    actions: {}
});

在 main.js 中给路由加一个全局前置守卫

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// main.js
//···
import auth from './auth';
import router from './router';
import store from './store';
import axios from './request';

Vue.prototype.$http = axios;

// 页面刷新时,重新赋值token
if (auth.getToken()) {
    store.commit('login', auth.getToken());
}

router.beforeEach((to, from, next) => { // 给路由添加一个全局前置守卫
    if (to.meta.requireAuth) { // 在路由配置中添加一个 meta.requireAuth 字段用于判断是否需要验证登录状态
        if (store.state.token) {
            // 通过vuex state获取当前的token是否存在
            next();
        } else {
            next({
                //如果token不存在, 跳转到登录页面, 并将当前页面的路由保存到url参数中, 以便登录成功后再跳转回当前页
                path: '/login',
                query: { redirect: to.fullPath }
            });
        }
    } else {
        next();
    }
});
//···

登录页面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Login.vue

// 省略...

login() { //点击登录按钮后执行
    this.$http
        .post(
            'http://127.0.0.1:8090/api',
            {
                account: this.from.username,
                password: this.from.password
            }
        )
        .then(e => {
            if (e.data.code === '200') {
                // 如果返回状态值等于200 将token存储到 cookie 中
                this.$store.commit('login', {
                    token: e.data.data.token,
                    identity: e.data.data.identity
                });
                let redirect = decodeURIComponent(
                    this.$route.query.redirect || '/'
                ); // 获取当前页面中的redirect参数, 用于登录成功后进行跳转
                this.$router.push({
                    path: redirect
                });// 跳转到登录前的页面
            } else {
                // 登录失败处理
            }
        })
        .catch(err => {
            console.log(err)
        });
}

// 省略...

退出登录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 省略...

logout() { // 点击退出登录按钮后
    this.$store.commit('logout'); // 调用 vuex 中的logout方法用于删除 token
    this.$router.replace({ // 跳转到登录页面
        path: '/login'
    });
}

// 省略...

至此, 一个简单的登录状态验证就搞定了@(撒花)

参考了:
摸手,带你用vue撸后台 系列二(登录权限篇)vue-axios-github

署名 - 非商业性使用 - 禁止演绎 4.0