primers

The background management page of the blog needs to have a login system, so consider doing a route authentication, the implementation method is also Nuxt official website gives the kernel to rewrite, incidentally will also be the front and back end of the route to the unified.

Routing to intercept

The front end mainly uses Nuxt middleware to do route interception, which also requires Vuex state tree to do.

middleware

middleware/auth.js
Copy the code

export default function ({ store, redirect }) {
  
  if(! store.state.user) {return redirect('/login')}}Copy the code

The page is redirected by authenticating whether the user information in the status tree exists

layouts/admin.vue
Copy the code
export default {
    middleware: 'auth',
    components: {
      AdminAside
    }
  }
Copy the code

Add middleware to the page layout of background management system

nuxtServerInit

In the NuxtJs rendering process, when a request comes in, the nuxtServerInit method is called first, which saves the server’s data beforehand.

We can use this method to receive Session information that stores user information.

nuxtServerInit ({ commit }, { req, res }) {
    if (req.session && req.session.user) {
      const { username, password } = req.session.user
      const user = {
        username,
        password
      }

      commit('SET_USER', user)
    }
  },
Copy the code

When the application is complete, some of the data we fetch from the server is filled into the state store.

According to the NuxtJs official website, the basic calculation of the page route authentication part is finished, the next part of the server code writing

Use Koa and KoA-session

Koa and Koa – the session

The backend code I use is Koa framework, and KOA-Session to do session processing.

When creating nuXT project, you can choose Koa framework directly

 vue init nuxt/koa
Copy the code

Related,

npm install koa-session
Copy the code

Overwrite in 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()

Copy the code

For the usage of KOA-session, see: Learn cookies and sessions from the KOA-Session middleware

Log on to the routing

/ / login the 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: 'Password error'})})Copy the code

At this point, the whole functional process is basically finished, and it is very smooth, but there is no such thing as plain sailing code for me.

session is not defined

The problem

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)
    }
  }
Copy the code

NuxtServerInit does not obtain any information about sessions, while other apis can obtain sessions, at that time, because of hard to find the cause, I suspected that there was a problem.

why

The final problem is still due to my carelessness and neglect of some details. In the chestnut provided on the official website:

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'})})Copy the code

It saves the session in req.session, so in nuxtServerInit session does exist in req.session, and the Koa2 and KOa-sessions THAT I’m using, Koa-session resolves the cookie to ctx.session, which does not exist in req.session.

To solve

So add session to request when nuxt.render is injected

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)
      })
    })
  })
Copy the code

And you’re done!