介绍
在本教程中,您将使用Auth
模块在 Nuxt.js应用程序中实现身份验证。
对于本教程的目的,您将使用JWT
进行身份验证。
以下是您将在本教程中构建的快速演示:
您可以在GitHub上找到此应用程序的源代码(https://github.com/do-community/nuxt-auth-app)。
<$>[警告] **警告:**本教程中的几个包现在包含具有已知漏洞的依赖性。在生产设置中,你会通过升级这些包,找到替代品或创建修补版本来解决这些问题。
前提条件
要完成本教程,您将需要:
- Node.js 本地安装,您可以按照 如何安装 Node.js 和创建本地开发环境进行操作。
- 克隆 API 需要有效的 Git 安装,请参阅 Getting Started with Git。
一些熟悉 Vue.js 和 Nuxt.js 可能是有益的. 如果你开始使用 Nuxt.js,你可以 参阅此帖子。
本教程已通过 Node v13.13.0、npm v6.14.4、vue v2.6.11 和 nuxt v2.12.2 进行验证。
步骤 1 – 旋转样本 API
但是,为了快速发展,本教程将克隆使用 AdonisJs构建的API。
火焰使用:
- JWT(JSON Web Tokens)用于身份验证
- SQLite
- CORS启用
API有三个终点:
/register
:用户注册的终端点/login
:用户身份验证的终端点/me
:获取当前身份验证的用户的详细信息的终端点,并且由auth
中间软件保护,这意味着用户必须进行身份验证才能访问终端点
首先,在您的终端窗口中运行以下命令:
1git clone https://github.com/do-community/jwt-auth-api.git
然后,导航到项目目录:
1cd jwt-auth-api
并安装 API 依赖:
1npm install
<$>[注]
注:在运行安装时,您可能会遇到与 sqlite3
版本 4.0.1
的问题,取决于您正在运行的 Node 版本。
在原来的发布时,Node 的最新版本是 10. 一个选项是将您的 Node 版本降级到 10.20.1
(了解到它正在接近终止支持)。
第二种选择是删除package-lock.json
文件,这将导致系统搜索4.2.0
,直到Node 13得到支持,您可能还需要将Node版本降级到13.13.0
。
第三种选择是将「package.json」修改为您当前版本的 Node 支持的「sqlite3」版本,删除「package-lock.json」并运行「npm install」。
其他不兼容性症状包括以下错误: TypeError: 无法读取 undefined 的属性 'data' 和
Error: 无法找到模块 '[...]/node_modules/sqlite3/lib/binding/[...]/node_sqlite3.node'。
然后将.env.example
重命名为.env
:
1mv .env.example .env
然后创建一个APP_KEY
:
1npx @adonisjs/[email protected] key:generate
你应该看到:
1[secondary_label Output]
2generated: unique APP_KEY
一旦完成,让我们运行迁移:
1npx @adonisjs/[email protected] migration:run
现在,您可以启动 API:
1# ensure that you are in the `jwt-auth-api` project directory
2npm start
您可以在「http://127.0.0.1:3333/api」上访问API。 让此操作在终端窗口中运行,直到本教程的剩余时间。
步骤 2 — 创建 Nuxt.js 应用
现在,您可以创建一个 Nuxt.js 应用程序. 打开一个新的终端窗口,并使用vue-cli
用 Nuxt 启动模板初始化一个新的 Vue 项目:
1npx [email protected] init nuxt/starter nuxt-auth
<$>[注] **注:**在测试时,‘vue-cli’被贬值,‘@vue/cli’是Vue项目的当前命令行工具,而‘@vue/cli-init’是传统‘vue-cli’项目的推荐方法,然而,‘create-nuxt-app’是现代Nuxt项目的推荐方法。
接下来,您需要导航到项目目录:
1cd nuxt-auth
安装依赖性:
1npm install
然后,您可以启动应用程序:
1npm run dev
該應用程式應在「http://localhost:3000」上執行,您可以在網頁瀏覽器中查看由「vue-cli」創建的默認 Vue 應用程式。
步骤 3 — 安装必要的 Nuxt.js 模块
现在,让我们安装应用程序所需的 Nuxt.js 模块,您将使用 Nuxt Auth 模块和 Nuxt Axios 模块,因为auth
模块内部使用 Axios:
1# ensure that you are in the `nuxt-auth` project directory
2npm install @nuxtjs/[email protected] @nuxtjs/[email protected] --save
一旦完成,打开nuxt.config.js
:
1nano nuxt.config.js
将下面的代码添加到 nuxt.config.js
:
1[label nuxt.config.js]
2module.exports = {
3 // ...
4
5 modules: [
6 '@nuxtjs/axios',
7 '@nuxtjs/auth'
8 ],
9}
<$>[注] **注:**此时,新版本的Nuxt可能会遇到错误:‘通过创建‘store/index.js’来启用 vuex store。
接下来,您需要设置模块,然后将下面的代码插入到 nuxt.config.js
:
1[label nuxt.config.js]
2module.exports = {
3 // ...
4
5 axios: {
6 baseURL: 'http://127.0.0.1:3333/api'
7 },
8
9 auth: {
10 strategies: {
11 local: {
12 endpoints: {
13 login: { url: 'login', method: 'post', propertyName: 'data.token' },
14 user: { url: 'me', method: 'get', propertyName: 'data' },
15 logout: false
16 }
17 }
18 }
19 }
20}
在这里,您设置了Axios在提出请求时使用的基本URL,在我们的情况下,我们正在引用我们之前设置的样本API。
然后,您定义本地
策略的身份验证终端,与您的 API 中的终端相匹配:
- 成功身份验证后,代币将在响应中作为一个
数据
对象中的代币
对象提供 - 同样,来自
/me
终端的响应将在一个数据
对象中提供 - 最后,您将
登录
设置为假
,因为您的 API 没有登录终端。
步骤 4 – 创建 Navbar 组件
要用你的心,你可以用你的心,你可以用你的心。
打开nuxt.config.js
,并将下面的代码粘贴到位于头部
对象内的链接
对象中:
1[label nuxt.config.js]
2module.exports = {
3 // ...
4 head: {
5 // ...
6 link [
7 // ...
8 {
9 rel: 'stylesheet',
10 href: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css'
11 }
12 ]
13 },
14 // ...
15}
现在,让我们创建Navbar组件:
1nano components/Navbar.vue
然后添加以下代码:
1[label components/Navbar.vue]
2<template>
3 <nav class="navbar is-light">
4 <div class="container">
5 <div class="navbar-brand">
6 <nuxt-link class="navbar-item" to="/">Nuxt Auth</nuxt-link>
7 <button class="button navbar-burger">
8 <span></span>
9 <span></span>
10 <span></span>
11 </button>
12 </div>
13 <div class="navbar-menu">
14 <div class="navbar-end">
15 <div class="navbar-item has-dropdown is-hoverable">
16 <a class="navbar-link">
17 My Account
18 </a>
19 <div class="navbar-dropdown">
20 <nuxt-link class="navbar-item" to="/profile">My Profile</nuxt-link>
21 <hr class="navbar-divider"/>
22 <a class="navbar-item">Logout</a>
23 </div>
24 </div>
25 <template>
26 <nuxt-link class="navbar-item" to="/register">Register</nuxt-link>
27 <nuxt-link class="navbar-item" to="/login">Log In</nuxt-link>
28 </template>
29 </div>
30 </div>
31 </div>
32 </nav>
33</template>
Navbar组件包含链接到登录
,注册
,配置文件
和登录
。
接下来,让我们更新默认布局以使用Navbar
组件。
打开Default.vue
:
1nano layouts/default.vue
将内容替换为以下内容:
1[label layouts/default.vue]
2<template>
3 <div>
4 <Navbar/>
5 <nuxt/>
6 </div>
7</template>
8
9<script>
10import Navbar from '~/components/Navbar'
11
12export default {
13 components: {
14 Navbar
15 }
16}
17</script>
接下来,让我们更新主页。
打开index.vue
:
1nano pages/index.vue
将内容替换为以下内容:
1[label pages/index.vue]
2<template>
3 <section class="section">
4 <div class="container">
5 <h1 class="title">Nuxt Auth</h1>
6 </div>
7 </section>
8</template>
在此时刻,你应该有一个应用程序,显示一个标题Nuxt Auth
与标题栏与导航链接:
步骤 5 – 处理用户注册
在页面
目录中,创建一个新的register.vue
文件:
1nano pages/register.vue
然后添加以下代码:
1[label pages/register.vue]
2<template>
3 <section class="section">
4 <div class="container">
5 <div class="columns">
6 <div class="column is-4 is-offset-4">
7 <h2 class="title has-text-centered">Register!</h2>
8
9 <Notification :message="error" v-if="error"/>
10
11 <form method="post" @submit.prevent="register">
12 <div class="field">
13 <label class="label">Username</label>
14 <div class="control">
15 <input
16 type="text"
17 class="input"
18 name="username"
19 v-model="username"
20 required
21 />
22 </div>
23 </div>
24 <div class="field">
25 <label class="label">Email</label>
26 <div class="control">
27 <input
28 type="email"
29 class="input"
30 name="email"
31 v-model="email"
32 required
33 />
34 </div>
35 </div>
36 <div class="field">
37 <label class="label">Password</label>
38 <div class="control">
39 <input
40 type="password"
41 class="input"
42 name="password"
43 v-model="password"
44 required
45 />
46 </div>
47 </div>
48 <div class="control">
49 <button type="submit" class="button is-dark is-fullwidth">Register</button>
50 </div>
51 </form>
52
53 <div class="has-text-centered" style="margin-top: 20px">
54 Already got an account? <nuxt-link to="/login">Login</nuxt-link>
55 </div>
56 </div>
57 </div>
58 </div>
59 </section>
60</template>
61
62<script>
63import Notification from '~/components/Notification'
64
65export default {
66 components: {
67 Notification,
68 },
69
70 data() {
71 return {
72 username: '',
73 email: '',
74 password: '',
75 error: null
76 }
77 },
78
79 methods: {
80 async register() {
81 try {
82 await this.$axios.post('register', {
83 username: this.username,
84 email: this.email,
85 password: this.password
86 })
87
88 await this.$auth.loginWith('local', {
89 data: {
90 email: this.email,
91 password: this.password
92 },
93 })
94
95 this.$router.push('/')
96 } catch (e) {
97 this.error = e.response.data.message
98 }
99 }
100 }
101}
102</script>
此表格包含三个字段:用户名
,电子邮件
和密码
。每个字段都与相应的组件数据相关联。在提交表单时,会被调用一个注册
方法。使用 Axios 模块,您将邮件请求发送到/register
终端,通过用户数据。如果注册成功,则使用 Auth 模块的loginWith()
,使用本地
策略并传输用户数据来登录用户。然后,您将用户重定向到主页。
如果出现错误,通知组件会显示错误消息。
在组件
中创建一个新的Notification.vue
文件:
1nano components/Notifaction.vue
然后将下面的代码插入其中:
1[label components/Notification.vue]
2<template>
3 <div class="notification is-danger">
4 {{ message }}
5 </div>
6</template>
7
8<script>
9export default {
10 name: 'Notification',
11 props: ['message']
12}
13</script>
通知组件接受一个消息
附件,即错误消息。
现在,你可以测试用户注册:
步骤 6 – 处理已登录的用户登录和退出
成功注册后,用户应该登录,但目前没有办法让应用程序知道用户是否已登录,所以让我们通过更新Navbar组件并添加一些计算属性来解决这个问题。
在你做这件事之前,让我们先通过在商店
目录中创建一个index.js
文件来激活Vuex商店。Auth模块将用户身份验证状态以及Vuex状态中的用户详细信息存储在一个auth
对象中,这样你就可以检查用户是否已登录到this.$store.state.auth.loggedIn
,如果没有用户登录,用户的详细信息也会变为null
。
<$>[注]
**注:**您还可以通过使用this.$auth.loggedIn
和this.$auth.user
的Auth模块直接访问用户身份验证状态和用户详细信息。
由于您可能希望在应用程序中的多个位置使用计算属性,所以让我们创建商店采集器。
打开index.js
:
1nano store/index.js
然后将下面的代码插入其中:
1[label store/index.js]
2export const getters = {
3 isAuthenticated(state) {
4 return state.auth.loggedIn
5 },
6
7 loggedInUser(state) {
8 return state.auth.user
9 }
10}
在这里,您创建了两个接口,第一个(‘isAuthenticated’)将返回用户的身份验证状态,第二个(‘loggedInUser’)将返回用户的详细信息或已登录的用户。
接下来,让我们更新 Navbar 组件,以使用 getters. 将 `components/Navbar.vue’ 的内容替换为以下:
1[label components/Navbar.vue]
2<template>
3 <nav class="navbar is-light">
4 <div class="container">
5 <div class="navbar-brand">
6 <nuxt-link class="navbar-item" to="/">Nuxt Auth</nuxt-link>
7 <button class="button navbar-burger">
8 <span></span>
9 <span></span>
10 <span></span>
11 </button>
12 </div>
13 <div class="navbar-menu">
14 <div class="navbar-end">
15 <div class="navbar-item has-dropdown is-hoverable" v-if="isAuthenticated">
16 <a class="navbar-link">
17 {{ loggedInUser.username }}
18 </a>
19 <div class="navbar-dropdown">
20 <nuxt-link class="navbar-item" to="/profile">My Profile</nuxt-link>
21 <hr class="navbar-divider"/>
22 <a class="navbar-item">Logout</a>
23 </div>
24 </div>
25 <template v-else>
26 <nuxt-link class="navbar-item" to="/register">Register</nuxt-link>
27 <nuxt-link class="navbar-item" to="/login">Log In</nuxt-link>
28 </template>
29 </div>
30 </div>
31 </div>
32 </nav>
33</template>
34
35<script>
36import { mapGetters } from 'vuex'
37
38export default {
39 computed: {
40 ...mapGetters(['isAuthenticated', 'loggedInUser'])
41 }
42}
43</script>
您使用扩散运算器(...
)创建计算属性,从mapGetters
中提取输出器,然后使用isAuthenticated
显示用户菜单或链接到login
或register
,取决于用户是否已登录。
现在,如果你给你的应用程序一个更新,你应该看到类似于下面的东西:
步骤 7 – 处理用户登录
现在,让我们允许返回用户登录的能力。
在页面
目录中创建一个新的login.vue
文件:
1nano pages/login.vue
然后将下面的代码插入其中:
1[label pages/login.vue]
2<template>
3 <section class="section">
4 <div class="container">
5 <div class="columns">
6 <div class="column is-4 is-offset-4">
7 <h2 class="title has-text-centered">Welcome back!</h2>
8
9 <Notification :message="error" v-if="error"/>
10
11 <form method="post" @submit.prevent="login">
12 <div class="field">
13 <label class="label">Email</label>
14 <div class="control">
15 <input
16 type="email"
17 class="input"
18 name="email"
19 v-model="email"
20 />
21 </div>
22 </div>
23 <div class="field">
24 <label class="label">Password</label>
25 <div class="control">
26 <input
27 type="password"
28 class="input"
29 name="password"
30 v-model="password"
31 />
32 </div>
33 </div>
34 <div class="control">
35 <button type="submit" class="button is-dark is-fullwidth">Log In</button>
36 </div>
37 </form>
38 <div class="has-text-centered" style="margin-top: 20px">
39 <p>
40 Don't have an account? <nuxt-link to="/register">Register</nuxt-link>
41 </p>
42 </div>
43 </div>
44 </div>
45 </div>
46 </section>
47</template>
48
49<script>
50import Notification from '~/components/Notification'
51
52export default {
53 components: {
54 Notification,
55 },
56
57 data() {
58 return {
59 email: '',
60 password: '',
61 error: null
62 }
63 },
64
65 methods: {
66 async login() {
67 try {
68 await this.$auth.loginWith('local', {
69 data: {
70 email: this.email,
71 password: this.password
72 }
73 })
74
75 this.$router.push('/')
76 } catch (e) {
77 this.error = e.response.data.message
78 }
79 }
80 }
81}
82</script>
这与注册
页面非常相似。表单中包含两个字段:电子邮件
和密码
。在提交表单时,会被调用一个登录
方法。使用Auth模块loginWith()
并通过用户数据,您会登录用户。如果验证成功,您会将用户重定向到主页。否则,将错误
设置为来自API响应的错误消息。再次,您正在使用先前的通知组件来显示错误消息。
步骤 8 – 显示用户配置文件
让我们允许登录的用户查看他们的个人资料。
在页面
目录中创建一个新的profile.vue
文件:
1nano pages/profile.vue
然后将下面的代码插入其中:
1[label pages/profile.vue]
2<template>
3 <section class="section">
4 <div class="container">
5 <h2 class="title">My Profile</h2>
6 <div class="content">
7 <p>
8 <strong>Username:</strong>
9 {{ loggedInUser.username }}
10 </p>
11 <p>
12 <strong>Email:</strong>
13 {{ loggedInUser.email }}
14 </p>
15 </div>
16 </div>
17 </section>
18</template>
19
20<script>
21import { mapGetters } from 'vuex'
22
23export default {
24 computed: {
25 ...mapGetters(['loggedInUser'])
26 }
27}
28</script>
注意您如何使用loggedInUser
接入器以显示用户详细信息。
点击我的个人资料
链接应显示一个我的个人资料
页面。
步骤 9 - 登录用户
更新 Navbar 组件内部的登录链接。
打开Navbar.vue
:
1nano components/Navbar.vue
更改登录链接以使用 @click="logout"
:
1[label components/Navbar.vue]
2// ...
3<div class="navbar-dropdown">
4 <nuxt-link class="navbar-item" to="/profile">My Profile</nuxt-link>
5 <hr class="navbar-divider"/>
6 <a class="navbar-item" @click="logout">Logout</a>
7</div>
8// ...
当点击logout
链接时,它会触发一个logout
方法。
接下来,让我们在Navbar组件的脚本部分中添加logout
方法:
1[label components/Navbar.vue]
2// ...
3
4export default {
5 // ...
6 methods: {
7 async logout() {
8 await this.$auth.logout();
9 },
10 },
11}
您将调用Auth模块的logout()
。这将从 localstorage中删除用户的代币,并将用户重定向到主页。
步骤 10 – 限制个人资料页面
现在,任何人都可以访问个人资料
页面,如果用户未登录,则会导致错误。
要解决此问题,您需要将个人资料页面限制在仅限于已登录的用户中。 幸运的是,我们可以通过Auth模块实现这一目标。
因此,让我们将auth
中间软件添加到profile
页面上,以以下方式更新script
部分:
1[label pages/profile.vue]
2// ...
3
4export default {
5 middleware: 'auth',
6 // ...
7}
现在,当未登录的用户尝试访问个人资料
页面时,用户将被重定向到登录
页面。
步骤 11 – 创建客人中间件
再一次,即使作为一个登录的用户,你仍然可以访问登录和注册页面。解决这一问题的一种方法是将登录和注册页面限制在没有登录的用户身上。
在middleware
目录中,创建一个新的guest.js
文件:
1nano middleware/guest.js
然后将下面的代码插入其中:
1[label middleware/guest.js]
2export default function ({ store, redirect }) {
3 if (store.state.auth.loggedIn) {
4 return redirect('/')
5 }
6}
一个中间件接受文本为其第一个论点,所以你从文本中提取商店
和重定向
。然后,你检查用户是否已登录,然后将用户重定向到主页。
接下来,让我们利用这个中间软件更新登录
和注册
的脚本
部分如下:
1[label pages/login.vue and pages/register.vue]
2// ...
3
4export default {
5 middleware: 'guest',
6 // ...
7}
现在,一切都将按预期运作。
结论
在本教程中,您研究了如何使用 Auth 模块在 Nuxt.js 应用程序中实现身份验证。
要了解有关 Auth 模块的更多信息,请参阅 docs。
如果您想了解有关 Vue.js 的更多信息,请参阅 我们的 Vue.js 主题页面以获取练习和编程项目。