您好,登錄后才能下訂單哦!
引子
博客的后臺管理頁面需要有登錄系統,所以考慮做一下路由鑒權,實現方式也是 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 的用法,可以參考:從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) }) }) })
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。