视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
nuxt框架中路由鉴权之Koa与Session使用方法
2020-11-27 19:47:57 责编:小采
文档


这次给大家带来nuxt框架中路由鉴权之Koa与Session使用方法,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: 800000,
 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 的用法,可以参考:从koa-session中间件学习cookie与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)
 })
 })
 })

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

jQuery实现模糊查询步骤详解

node Async/Await 异步编程实现详解

下载本文
显示全文
专题