因我们把登录请求写在了vuex的actions中,当点击登录按钮,我们需要把用户名和密码dispatch给vuex的actions中的Login,这时将发送请求给后端登录接口进行验证,后端则去数据库中查看用户名和密码是否正确,若正确,则返回一个token值给前端,否则则登录失败
登录页面的代码实现如下:
// 这是点击登录按钮后的回调函数
// this.loginForm是存放用户名和密码的对象
this.$store.dispatch('Login', this.loginForm).then(() => {
this.loading = false;
// 当用户名和密码正确后,则将用户名和密码存放在cookie中,并设置过期时间
setCookie("username",this.loginForm.username,15);
setCookie("password",this.loginForm.password,15);
// 跳转到首页
this.$router.push({path: '/'})
}).catch(() => {
this.loading = false
})
vuex中的Login实现代码如下:
state: {
token: getToken() // 首先是先获得浏览器中的token值
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
},
actions: {
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
// login是发送登录请求的函数,其中将用户名和密码作为参数
login(username, userInfo.password).then(response => {
// 返回了成功的回调,则会获得token值
const data = response.data
const tokenStr = data.tokenHead+data.token
// setToken函数会将tokenStr存在浏览器的cookie中
setToken(tokenStr)
// 并提交给mutations将tokenStr存在vuex中state中
commit('SET_TOKEN', tokenStr)
// 返回成功的回调
resolve()
}).catch(error => {
reject(error)
})
}),
// 登出
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
},
// 前端 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
}
},
存取token的函数文件
import Cookies from 'js-cookie'
const TokenKey = 'loginToken'
// 取出loginToken的值
export function getToken() {
return Cookies.get(TokenKey)
}
// 设置loginToken的值在浏览器cookie中
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
// 移除loginToken
export function removeToken() {
return Cookies.remove(TokenKey)
}
登录请求的函数
// 发送post请求并携带用户名和密码
export function login(username, password) {
return request({
url: '/admin/login',
method: 'post',
data: {
username,
password
}
})
}
在axios的每次请求的拦截器中都需要在请求头中加入token值,后端验证token值是否有效,若有效则返回数据
import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import store from '../store'
import { getToken } from '@/utils/auth'
// 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 15000 // 请求超时时间
})
// request拦截器
service.interceptors.request.use(config => {
if (store.getters.token) {
config.headers['Authorization'] = getToken()
// 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
}, error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
})
// respone拦截器
service.interceptors.response.use(
response => {
/**
* code为非200是抛错 可结合自己业务进行修改
*/
const res = response.data
if (res.code !== 200) {
Message({
message: res.message,
type: 'error',
duration: 3 * 1000
})
// 401:未登录;
if (res.code === 401) {
MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 因token无效,所以则dispatch给FedLogOut移除cookie中和vuex中存放的token值
// FedLogOut的实现在上面的vuex代码中
store.dispatch('FedLogOut').then(() => {
location.reload()// 为了重新实例化vue-router对象 避免bug
})
})
}
return Promise.reject('error')
} else {
// 响应没问题,则正常返回数据
return response.data
}
},
error => {
console.log('err' + error)// for debug
Message({
message: error.message,
type: 'error',
duration: 3 * 1000
})
return Promise.reject(error)
}
)
export default service
每次路由跳转前,在路由守卫中判断浏览器是否存在token值,若存在,则允许跳转,否则,则跳转到登录页面
const whiteList = ['/login'] // 不重定向白名单
router.beforeEach((to, from, next) => {
if (getToken()) {
// 存在token,且是要进入login页面,则让其跳转到首页
if (to.path === '/login') {
next({ path: '/' })
} else {
// 检查人物列表数据是否为空,则为空,则去请求人物数据,则放入vuex中getters
if (store.getters.roles.length === 0) {
store.dispatch('GetInfo').then(res => { // 拉取用户信息
let menus=res.data.menus;
let username=res.data.username;
store.dispatch('GenerateRoutes', { menus,username }).then(() => {
// 生成可访问的路由表
router.addRoutes(store.getters.addRouters); // 动态添加可访问路由表
next({ ...to, replace: true })
})
}).catch((err) => {
store.dispatch('FedLogOut').then(() => {
Message.error(err || 'Verification failed, please login again')
next({ path: '/' })
})
})
} else {
// 不为空则正常跳转
next()
}
}
} else {
// 如果不存在token,且是跳转到登录页,则正常跳转
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/login')
NProgress.done()
}
}
})
退出登录的代码实现如下:
// 点击了退出后的回调函数
logout() {
// LogOut是vuex中的actions实现,其代码可以看上面的vuex代码
// 清除了浏览器和vuex中的token值,并将存放人物列表置为空数组
this.$store.dispatch('LogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
}
以上若有不足之处欢迎指正!!!!!!!