创建前端认证

你将发现这一节简单而熟悉,因为你在前两章中已经使用虚拟后端身份验证构建了几个身份验证 Nuxt 应用。本章的区别在于,我们正在构建跨域应用,而不是像前两章那样的单域应用。你可以在 /chapter-10/nuxt-universal/nuxtServerInit//chapter-11/nuxt-universal/route-middleware/per-route/ 中回顾这些单域 Nuxt 应用。

此外,我们将再次使用我们在第六章 “编写插件和模块” 中已经介绍过的 Nuxt 模块:@nuxtjs/axios@nuxtjs/proxy。你可以在 /chapter-6/nuxt-universal/modules-snippets/top-level/ 中回顾采用这两个模块的 Nuxt 应用。但现在,让我们为这个我们将从前几章重构的 Nuxt 应用安装和配置它们,以创建客户端身份验证,步骤如下:

  1. 通过 npm 安装 @nuxtjs/axios@nuxtjs/proxy

    $ npm i @nuxtjs/axios
    $ npm i @nuxtjs/proxy
  2. Nuxt 配置文件中配置这两个模块,如下所示:

    // nuxt.config.js
    module.exports = {
      modules: [
        '@nuxtjs/axios',
      ],
      axios: {
        proxy: true
      },
      proxy: {
        '/api/': { target: 'http://localhost:4000/', pathRewrite: {'^/api/': ''} },
      }
    }

    由于我们知道在前面几节中创建的远程 API 服务器运行在 localhost:4000,在此配置中,我们将此 API 地址分配给 proxy 选项中的 /api/ 键。

  3. 删除之前用于导入 axios Node.js 模块的任何 import 语句;例如,在受保护的页面上:

    // pages/secured.vue
    import axios from '~/plugins/axios'

    这是因为我们现在使用的是 @nuxtjs/axiosNuxt Axios 模块),我们将不再需要在我们的代码中直接导入原始的 axios Node.js 模块。

  4. 通过使用 $axios 调用 Nuxt Axios 模块,并替换之前在我们的代码中用于 HTTP 请求的 axios(来自原始的 axios Node.js 模块);例如,在受保护的页面上:

    // pages/secured.vue
    async asyncData ({ $axios, redirect }) {
      const { data } = await $axios.$get('/api/private')
    }

Nuxt Axios 模块通过步骤 2 中的 Nuxt 配置文件加载到我们的 Nuxt 应用中,因此我们可以使用 $axiosNuxt 上下文或 this 访问它。

我们还应该使用这两个 Nuxt 模块——@nuxtjs/axios@nuxtjs/proxy,以及 cookiesNode.js 模块(客户端和服务器端),重构此应用中 store 和中间件的其余代码。让我们在接下来的章节中开始吧。

在这个应用中,我们不再使用会话来 “记住” 已验证的数据。相反,我们将使用 js-cookie Node.js 模块来创建 cookie,以存储来自远程服务器的数据。

使用这个 Node.js 模块可以非常容易地创建一个在整个站点都存在的 cookie;例如:

  1. 使用以下格式设置 cookie

    Cookies.set(<name>, <value>)

    如果你想创建一个 30 天后过期的 cookie,可以使用以下代码:

    Cookies.set(<name>, <value>, { expires: 30 })
  2. 使用以下格式读取 cookie

    Cookies.get(<name>)

你可以看到使用这个 Node.js 模块是多么容易——你只需要 setget 方法来在客户端设置和检索你的 cookie。因此,让我们按照以下步骤重构我们 store 中的代码:

  1. 使用 if 三元条件,仅当我们的 Nuxt 应用在客户端处理时才导入 js-cookie Node.js 模块:

    // store/actions.js
    const cookies = process.client ? require('js-cookie') : undefined
  2. 使用 js-cookieset 函数将来自服务器的数据作为 auth 存储在 login action 中,如下所示:

    // store/actions.js
    export default {
      async login(context, { username, password }) {
        const { data } = await
          this.$axios.$post('/api/public/login/local',
            { username, password })
        cookies.set('auth', data)
        context.commit('setAuth', data)
      }
    }
  3. 使用 js-cookieremove 函数删除 logout action 中的 auth cookie,如下所示:

    // store/actions.js
    export default {
      logout({ commit }) {
        cookies.remove('auth')
        commit('setAuth', null)
      }
    }

这不是很简单吗?但是,你可能会问:我们使用这个 auth cookie 做什么,以及如何使用?让我们在下一节关于在 Nuxt 服务器端使用 cookie 的内容中找到答案。

有关此 Node.js 模块的更多信息和代码示例,请访问 https://github.com/js-cookie/js-cookie。

由于我们使用 js-cookie 将带有 JWT 的身份验证数据哈希并存储在名为 authcookie 中,因此每当我们需要它时,都需要读取和解析这个 cookie。这时,Node.js 模块 cookie 就派上用场了。同样,我们在之前的章节中也使用过这个 Node.js 模块,但我们没有详细讨论过它。

cookie Node.js 模块是一个用于 HTTP 服务器的 HTTP cookie 解析器和序列化器。它用于在服务器端解析 cookie 标头。让我们看看如何在以下步骤中对 auth cookie 使用它:

  1. 使用 if 三元条件,仅当我们的 Nuxt 应用在服务器端处理时才导入 cookie Node.js 模块:

    // store/index.js
    const cookie = process.server ? require('cookie') : undefined
  2. 使用 cookie Node.js 模块的 parse 函数解析 nuxtServerInit action 中 HTTP 请求标头中的 auth cookie,如下所示:

    // store/index.js
    export const actions = {
      nuxtServerInit({ commit }, { req }) {
        if (req.headers.cookie && req.headers.cookie.indexOf('auth') > -1) {
          let auth = cookie.parse(req.headers.cookie)['auth']
          commit('setAuth', JSON.parse(auth))
        }
      }
    }
  3. 通过 $axios 使用 Nuxt Axios 模块的 setHeader 函数,在 token 中间件中包含 HTTP 标头中的令牌 (JWT),以便访问远程服务器上的私有 API 路由,如下所示:

    // middleware/token.js
    export default async ({ store, error, $axios }) => {
      if (!store.state.auth.token) {
        // 处理错误
      }
      $axios.setHeader('Authorization', `Bearer: ${store.state.auth.token}`)
    }
  4. 使用 npm run dev 运行 Nuxt 应用。你应该在浏览器上的 localhost:3000 看到应用正在运行。你可以在登录页面使用凭据登录,然后访问受 JWT 保护的受限安全页面。

做得好!你已经完成了基于令牌的本地身份验证。你已经重构了 store 和中间件中的代码,使 js-cookiecookie Node.js 模块在 Nuxt 应用中完美地协同工作,并在客户端和服务器端互补,以实现前端身份验证。此外,你还通过跨域方法成功地将 Nuxt 应用与 API 解耦。

正如你所见,使用 js-cookiecookie Node.js 模块进行前端身份验证既简单又强大。但它也可以通过 Google OAuth 实现,我们将在下一节中介绍。将 Google OAuth 添加到前端身份验证可以为用户提供一个额外的登录选项。所以,让我们开始吧。

你可以在我们的 GitHub 仓库的 /chapter-12/nuxt-universal/cross-domain/jwt/axios-module/frontend/ 中找到此 Nuxt 应用的源代码。

有关 cookie Node.js 模块的更多信息和代码示例,请访问 https://github.com/jshttp/cookie。

有关 Nuxt Axios 模块的辅助函数(例如 setHeader 辅助函数)的更多信息,请访问 https://axios.nuxtjs.org/helpers。