Nuxt服务端渲染:后端接口身份验证

一、Nuxt项目的不同请求流程

Nuxt服务端渲染解决了Vue单页应用SEO的痛点,但是在权限认证上也带来了一些麻烦。Nuxt项目中,用户切换路由时请求页面和在页面中触发ajax请求数据的的路径是不同的。

具体流程如下图:

上图中,前端即浏览器端,服务端即后台服务(比如python或java),后台服务和nuxt服务中间层也是运行在服务器的。

    • 进入页面时,因为要先访问nuxt服务进行服务端渲染,此时需要nuxt服务向后台服务请求数据。
    • 而在页面中触发ajax请求(比如评论等)时,浏览器发出请求时直达后台服务

二、Nuxt身份验证

1. 普通单页应用ajax的身份验证

Web应用的身份验证依赖登录后后端给前端的身份凭证,即常说的token,是一串字符串,后端可以根据该token对访问者进行身份验证。

正常的单页应用中,我们都是前端直接发送ajax请求到后台服务。前端登录获取到token后,可以将token存储到cookie或者localStorage中。不同之处是cookie在浏览器请求时可以自动携带,而存在localStorage则需要使用请求头将token带到后端。

token存储localStorage中,axios作为请求库,可以这样设置请求token:

export function getToken () {
  return localStorage.getItem('token')
}

const beforeRequest = (config) => {
  config.headers['token'] = getToken()
  return config
}

const instance = axios.create({
  baseURL: xxx,
  timeout: 60 * 1000,
  headers: {}
})

instance.interceptors.request.use(beforeRequest)

2. nuxt身份验证

对于nuxt,服务端渲染需要的数据是nuxt服务发出的,此时是是在服务器环境下,并没有localStorage,无法直接获取到token

不过我们可以把token存储在浏览器cookie中,这样浏览器发起的页面请求就会自动带上token。nuxt服务收到页面请求时,获取token并缓存下来,在发往后台服务时设置请求头即可。

如何获取token并缓存呢?nuxt中的中间件,访问页面时会先经过中间件的处理。我们创建一个简单的中间件,将cookie缓存下来:

const serverCookieCache = {
  cookie: '',
  set (value) {
    serverCookieCache.cookie = value
  }
}

// middleware/cookie.js
export default function ({ req }) {
  if (process.server) {
    serverCookieCache.set(req.headers.cookie || '')
  }
}

这里将cookie缓存一下,然后我们可以写一个服务器环境和浏览器环境通用的获取token接口:

function getCookie (cookie, key) {
  if (!cookie) return ''
  let cookieList = cookie.split('; ')
  let keyInfo = cookieList.reduce((info, cookieItem) => {
    let [key, value] = cookieItem.split('=')
    info[key] = value
    return info
  }, {})
  return keyInfo[key] || ''
}

export function getToken () {
  const cookies = process.server ? serverCookieCache.cookie : document.cookie
  return getCookie(cookies, 'token')
}

axios设置一下请求头:

const beforeRequest = (config) => {
  let token = getToken()
  config.headers['token'] = token
  return config
}
const instance = axios.create({
  baseURL: `xxx`,
  timeout: 60 * 1000,
})
instance.interceptors.request.use(beforeRequest)

至此,从浏览器和nuxt服务发出的请求,通过同一套axios代码向后台请求数据,都实现了带token进行身份验证。

¥赞赏