Login Module
Needs to be done to guard the route, some modules are to be protected, you must be logged in to visit. Common practice is to add routes meta:{ auth:true }
to do the identification, it expressed the need to do certification.
// 路由守卫
router.beforeEach((to, from, next) => {
// 判断要进入的路由是否需要认证
if(to.meta.auth) {
// 通过token令牌机制判断是否已经登录
const token = localStorage.getItem('token');
if (token) {
next(); // 如果登录则放行,进入路由
} else {
// 跳转,并携带重定向地址
next({
path: '/login',
query: {
redirect: to.path
}
});
}
} else {
// 不需要验证的模块,直接放行
next();
}
});
In Vuex stored login status isLogin
import Vue from 'vue'
import Vuex from 'vuex'
import user from './service/user'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
isLogin: localStorage.getItem('token') ? true : false
},
mutations: {
setLoginState(state, bool) {
state.isLogin = bool;
// true 表示登录,false 表示注销
}
},
actions: {
login({commit}, user) {
// 发起登录请求,请求都拆分出去 service 文件夹中
// 使用 service 的请求方法
user.login(user).then(res => {
// 从 res.data 中解构数据,code和token
const { code, token } = res.data;
if (code) {
// 登录成功,修改Vuex中间的登录状态
commit('setLoginState', true);
// 缓存令牌 token
localStorage.setItem("token", token);
}
return code; // 返回code 给下一个 .then 使用
});
},
logout({ commit }) {
// 清除缓存
localStorage.removeItem('token');
// 重置状态
commit('setLoginState', false);
}
}
});
service
Folder service
// 返回一个 Promises 方便外面使用
import axios from 'axios'
export default {
login(user) {
// 注意:请求地址最好是抽出去统一管理
return axios.get('/api/login', {
params: user
});
}
}
Log submit event processing components
// 提交函数中, dispatch 是调用 actios 中的方法,在通过 commit 发送 mutations 方法修改数据
// 注意:this.model 就是传递的数据
this.$store.dispatch("login", this.model)
.then(code => {
if (code) {
// 登录成功后,重定向,如果没有则重定向到首页
const path = this.$route.query.redirect || '/';
this.$router.push(path);
}
}).catch(error => {
// 有错误发生 或 登录失败
const toast = this.$createToast({
time: 2000,
text: error.message || error.response.data.message || "登录失败",
type: "error"
});
toast.show();
});
Checkpoints need to be considered
- How to guard the route
- How asynchronous operation
- Saving registration status
- How analog interface
HTTP Interceptor
New interceptor.js
file, requests and responses for intercepting
// token 过期导致请求失败的情况可能出现在项目的任何地方,可以通过响应拦截统一处理
// 拦截器的作用:是对接口做一层保护,表示所有的接口都会带有令牌 token
// 可以查看 axios 的文档 : http://www.axios-js.com/zh-cn/docs/
const axios = require('axios');
export default function(vm) {
// HTTP 请求拦截器
axios.interceptors.request.use(config => {
// 在发送请求之前做些什么
// 获取token, 并添加到 headers 请求头中
const token = localStorage.getItem('token');
if (token) {
config.headers.token = token;
}
return config;
});
// HTTP 响应拦截器
// 统一处理 401 状态,token 过期的处理,清除token跳转login
// 参数 1, 表示成功响应
axios.interceptors.response.use(null, err => {
// 没有登录或令牌过期
if (err.response.status === 401) {
// 注销,情况状态和token
vm.$store.dispatch("logout");
// 跳转的登录页
vm.$storer.push('/login');
// 注意: 这里的 vm 实例需要外部传入
}
return Promise.reject(err);
});
}
// 使用拦截器
// 1. 引入拦截器文件
import interceptor from './interceptor'
// 执行拦截器初始化
interceptor(vm);
Logout
- In both cases token need to clear the cache:
- Users initiative to cancel
- token expired
- It needs to be done:
- Empty the cache
- Reset login status
methods: { logout() { this.$route.dispatch('login'); } }
Token-depth understanding of the mechanism
- Bearer Token Specification
- Concept: Describes how to use tokens in the HTTP specification OAuth2 access to protected resources
- Features: Token is the ID card, no need to prove ownership of the token
- Specifications: Auuthorization defined in the request header: Bearer token
- Json Web Token specification https://jwt.io
- Concept: the way tokens specific definition
- States: the first token configuration, payload, signed by three parts
- Head: contains the encryption algorithm, the token type and other information
- Load: containing user information, the issue of time, and expiration time information
- Signature: the hash string obtained according to the header, payload and a secret key encryption