nuxt框架中路由鉴权之Koa和Session的用法
引子
博客的后台管理页面需要有登录系统,所以考虑做一下路由鉴权,实现方式也是 nuxt 官网给出栗子来改写,顺便也将前后端路由给统一了。
路由拦截
前端方面主要通过利用 nuxt 的中间件来做路由拦截,这里也是需要 vuex 状态树来做。
middleware
middleware/auth.js
export default function ({ store, redirect }) { if (!store.state.user) { return redirect('/login') } }
通过对状态树上的用户信息是否存在来鉴权,来对页面进行重定向
layouts/admin.vue
export default { middleware: 'auth', components: { adminaside } }
在后台管理系统的页面布局上添加 中间件
nuxtserverinit
在 nuxtjs 的渲染流程中,当请求打入时,最先调用的即是 nuxtserverinit 方法,可以通过这个方法预先将服务器的数据保存。
我们可以利用该方法来接收存储用户信息的 session 信息。
nuxtserverinit ({ commit }, { req, res }) { if (req.session && req.session.user) { const { username, password } = req.session.user const user = { username, password } commit('set_user', user) } },
当应用完毕时,一些我们从服务器获取到的数据就会被填充到这个状态树 (store) 上。
按照 nuxtjs 官网给出的栗子来看,到这里基本算把页面中路由鉴权部分写完了,接下来是对服务器端该部分代码的写作
使用koa和koa-session
koa和koa-session
后端代码我采用是 koa 框架,以及 koa-session 来对 session 做处理。
在新建 nuxt 项目的时候直接选用 koa 框架即可
vue init nuxt/koa
相关依赖
npm install koa-session
在 server.js 中改写
import koa from 'koa' import { nuxt, builder } from 'nuxt' // after end import session from 'koa-session' async function start () { const app = new koa() const host = process.env.host || '127.0.0.1' const port = process.env.port || 7998 // import and set nuxt.js options let config = require('../nuxt.config.js') config.dev = !(app.env === 'production') // instantiate nuxt.js const nuxt = new nuxt(config) // build in development if (config.dev) { const builder = new builder(nuxt) await builder.build() } // body-parser app.use(bodyparser()) // mongodb // session app.keys = ['some session'] const config = { key: 'session', /** (string) cookie key (default is koa:sess) */ /** (number || 'session') maxage in ms (default is 1 days) */ /** 'session' will result in a cookie that expires when session/browser is closed */ /** warning: if a session cookie is stolen, this cookie will never expire */ maxage: 86400000, overwrite: true, /** (boolean) can overwrite or not (default true) */ httponly: true, /** (boolean) httponly or not (default true) */ signed: true, /** (boolean) signed or not (default true) */ rolling: false /** (boolean) force a session identifier cookie to be set on every response. the expiration is reset to the original maxage, resetting the expiration countdown. default is false **/ } app.use(session(config, app)) // routes app.use(async (ctx, next) => { await next() ctx.status = 200 // koa defaults to 404 when it sees that status is unset return new promise((resolve, reject) => { ctx.res.on('close', resolve) ctx.res.on('finish', resolve) nuxt.render(ctx.req, ctx.res, promise => { // nuxt.render passes a rejected promise into callback on error. promise.then(resolve).catch(reject) }) }) }) app.listen(port, host) console.log('server listening on ' + host + ':' + port) // eslint-disable-line no-console } start()
对于 koa-session 的用法,可以参考:
登录路由
// 登录 router.post('/api/login', async (ctx, next) => { const { username, password } = ctx.request.body let user, match try { user = await admin.findone({ user: username }).exec() if (user) { match = await user.comparepassword(password, user.password) } } catch (e) { throw new error(e) } if (match) { ctx.session.user = { _id: user._id, username: user.user, nickname: user.nickname, role: user.role } console.log(ctx.session) return (ctx.body = { success: true, data: { username: user.user, nickname: user.nickname } }) } return (ctx.body = { success: false, err: '密码错误' }) })
写到这里,整个功能流程基本完毕了,也非常的顺畅,但是对我来说一帆风顺的代码是不存在的。
session is not defined
问题
nuxtserverinit ({ commit }, { req, res }) { if (req.session && req.session.user) { // res.session is not defined const { username, password } = req.session.user const user = { username, password } commit('set_user', user) } }
在 nuxtserverinit 获取不到有关 session 的任何信息,然而其他的 api 均可获取到 session ,当时由于苦苦找不到原因,一度怀疑栗子有问题。。
原因
最终的问题还是因为自己的粗心,忽视了一些细节,在官网给出的栗子中:
app.post('/api/login', function (req, res) { if (req.body.username === 'demo' && req.body.password === 'demo') { req.session.authuser = { username: 'demo' } return res.json({ username: 'demo' }) } res.status(401).json({ error: 'bad credentials' }) })
它将 session 保存在了 req.session , 所以在 nuxtserverinit session也确实存在于 req.session ,而我使用的 koa2 和 koa-session , koa-session 将 cookie 解析到了 ctx.session , 它并不存在于 req.session 。
解决
所以在将 nuxt.render 注入的时候,将 session 添加进 request 中
app.use(async (ctx, next) => { await next() ctx.status = 200 // koa defaults to 404 when it sees that status is unset ctx.req.session = ctx.session return new promise((resolve, reject) => { ctx.res.on('close', resolve) ctx.res.on('finish', resolve) nuxt.render(ctx.req, ctx.res, promise => { // nuxt.render passes a rejected promise into callback on error. promise.then(resolve).catch(reject) }) }) })
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: vue实现2048小游戏功能思路详解
下一篇: 蓝桥杯JavaB组---振兴中华