vue+koa2实现session、token登陆状态验证的示例(2)

const Koa = require('koa') const app = new Koa() const jwt = require('jsonwebtoken') const bodyParser = require('koa-bodyparser') const Router = require('koa-router') const router = new Router() const tokenConfig = {privateKey: 'xxxxxxxxxxxx'} // 加密密钥 app.use(bodyParser()) app.use(router.routes()).use(router.allowedMethods())

3、登陆路由

router.post('/login', async (ctx) => { try { const data = ctx.request.body.data const { username, password } = data if (true) { const userInfo = {username: '', userID: ''} const token = jwt.sign(userInfo, tokenConfig.privateKey, {expiresIn: '7d'}) // 签发 token, 7天有效期 ctx.body = {code: 1, message: '登陆成功', data: {token: 'Bearer ' + token}} } else { ctx.body = {code: 0, message: '账号或密码错误'} } } catch(err) { throw new Error(err) } })

前端登陆

axios.post('/login', {username: '', password: ''}).then(res => { if (res.data.code === 1) { localStorage.setItem('token', res.data.data.token) // vuex 存储 userInfo 和登陆状态 store.commit('SET_USERINFO', {userInfo: res.data.data.userInfo, status: true}) } })

4、校验是否已登陆

router.get('/getUserInfo', async (ctx) => { try { const token = ctx.get('Authorization') // 获取请求 Header 中 Authorization 值 let userInfo = {} if (token === '') { ctx.body = {code: 0, message: '未登陆'} } else { try { userInfo = jwt.verify(token.split(' ')[1], tokenConfig.privateKey) // 验证 token ctx.body = {code: 1, message: '已登陆', data: {userInfo: userInfo: loginStatus: true}} } catch(err) { // token 过期或无效 ctx.body = {code: 0, message: '未登陆', data: {userInfo: {}: loginStatus: false}}} } } } catch(err) { throw new Error(err) } })

要每次的请求中都带上 token 信息,要给 axios 设置请求拦截

// 请求拦截,在每次请求中的 header 中带上 token axios.interceptors.request.use(config => { let token = localStorage.getItem('token') if (token) { config.headers.common.Authorization = token } return config }, error => { return Promise.reject(error); })

每次进入页面之前要判断下是否已登陆,是否有权限进入该页面,之前我是在每个页面的 created 钩子函数中去请求 '/getUserInfo' 判断是否以登陆,这样做繁琐,并且页面会先呈现一下,然后一闪而过(验证不过的情况下),在路由钩子函数中可全局配置

// 路由守卫, 在跳转之前执行 router.beforeEach((to, from, next) => { let token = localStorage.getItem('token') let requireAuth = to.meta.requireAuth // VueRouter 里配置页面是否需要登陆进入 let root = to.meta.root // VueRouter 里配置页面是否需要登陆且管理员权限进入 if (!token) { // vuex 清除 userInfo 和登陆状态 store.commit('SET_USERINFO', {userInfo: {}, status: false}) requireAuth ? next({path: 'https://www.jb51.net/'}) : next() } else { axios.get(API.getUserInfo).then(res => { // vuex 存储 userInfo 和登陆状态 store.commit('SET_USERINFO', {userInfo: res.data.userInfo, status: res.data.loginStatus}) if (requireAuth) { if (!res.data.loginStatus || (root && !res.data.userInfo.root)) { next({path: 'https://www.jb51.net/'}) } else { next() } } else { next() } }) } }) /** VueRouter { path: '/admin', name: 'admin', meta: { requireAuth: true, root: true }, } */

5、退出登陆

因为服务器端并没有存储用户登陆相关信息,只与前端是否存在 token 或是否能验证通过有关,所以退出登陆就将 token 清除即可

methods: { logout() { localStorage.removeItem('token') // vuex 清除登陆信息 store.commit('SET_USERINFO', {userInfo: {}, status: false}) if (this.$route.path !== 'https://www.jb51.net/') { this.$router.push({path: 'https://www.jb51.net/'}) } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/d0d0be23f4c29f6a9c4771fa652dbc79.html