当前位置: 首页 > 工具软件 > Sleek.js > 使用案例 >

nuxt.js 全局 js_如何在Nuxt.js应用程序中实现身份验证

娄丁雨
2023-12-01

nuxt.js 全局 js

In this tutorial, you’ll implement authentication in a Nuxt.js app using the Auth module. For the purpose of this tutorial we’ll be using JWT for authentication.

在本教程中,您将使用Auth模块在Nuxt.js应用中实现身份Auth 。 就本教程而言,我们将使用JWT进行身份验证。

Below is a quick demo of what we’ll be building in this tutorial.

以下是我们将在本教程中构建的快速演示。

启动快速API (Spinning up a quick API)

To save ourselves some time, we’ll clone an API, which you can do with the following command:

为了节省时间,我们将克隆一个API,您可以使用以下命令进行操作:

  • git clone https://github.com/ammezie/jwt-auth-api.git

    git clone https://github.com/ammezie/jwt-auth-api.git

Then we install the API dependencies:

然后,我们安装API依赖项:

  • cd jwt-auth-api

    cd jwt-auth-api
  • npm install

    npm安装

Next, rename .env.example to .env and generate an APP_KEY:

接下来,将.env.example重命名为.env并生成一个APP_KEY

With the adonis CLI:

使用adonis CLI:

  • adonis key:generate

    阿多尼斯密钥:生成

Without the adonis CLI:

没有adonis CLI:

  • node ace key:generate

    节点ace密钥:生成

Once that’s done, let’s run the migrations:

完成后,让我们运行迁移:

With the adonis CLI:

使用adonis CLI:

  • adonis migration:run

    阿多尼斯迁移:运行

Without the adonis CLI:

没有adonis CLI:

  • node ace migration:run

    节点ace迁移:运行

Before we move on to building the Nuxt.js app, let’s quickly go over the API. The API is built using AdonisJs and it uses JWT (JSON Web Tokens) for authentication. It also uses SQLite.

在继续构建Nuxt.js应用之前,让我们快速浏览一下API。 该API使用AdonisJs构建 ,并且使用JWT(JSON Web令牌)进行身份验证。 它还使用SQLite。

The API has three endpoints:

该API具有三个端点:

  • /register: endpoint for users registration.

    /register :用户注册的端点。

  • /login: endpoint for authenticating users.

    /login :用于验证用户的端点。

  • /me: endpoint for getting details for the currently authenticated user and it is protected by an auth middleware, which means a user must be authenticated to access the endpoint.

    /me :端点,用于获取当前已认证用户的详细信息,并且受auth中间件保护,这意味着必须对用户进行认证才能访问该端点。

The API also already has CORS enabled.

该API也已经启用了CORS。

Now, we can start the API:

现在,我们可以启动API:

  • npm start

    npm开始

We can access the API on http://127.0.0.1:3333/api. We’ll leave it running.

我们可以通过http://127.0.0.1:3333/api访问API。 我们将继续运行。

Note: Though I’ll be using an API built with AdonisJs for the purpose of this tutorial, you are free to use whatever framework that work best for you.

注意:尽管本教程将使用AdonisJs构建的API,但您可以自由使用最适合您的框架。

创建一个Nuxt.js应用 (Creating a Nuxt.js App)

For this, we’ll make use of the Vue CLI, so you need to first install the Vue CLI in case you don’t have it installed already:

为此,我们将使用Vue CLI,因此,如果尚未安装Vue CLI,则需要先安装它:

  • npm install -g vue-cli

    npm install -g vue-cli

Then we can create a Nuxt.js app:

然后,我们可以创建一个Nuxt.js应用程序:

  • vue init nuxt/starter nuxt-auth

    vue初始化nuxt /启动程序nuxt-auth

Next, we need to install the dependencies:

接下来,我们需要安装依赖项:

  • cd nuxt-auth

    cd nuxt-auth
  • npm install

    npm安装

We can launch the app:

我们可以启动该应用程序:

  • npm run dev

    npm run dev

The app should be running on http://localhost:3000.

该应用程序应在http://localhost:3000

安装必要的Nuxt.js模块 (Installing Necessary Nuxt.js Modules)

Now, let’s install the Nuxt.js modules that we’ll be needing for our app. We’ll be using the Nuxt Auth module and the Nuxt Axios module, since the auth module makes use of Axios internally:

现在,让我们安装应用程序所需的Nuxt.js模块。 我们将使用Nuxt Auth模块Nuxt Axios模块 ,因为auth模块在内部使用Axios:

  • npm install @nuxtjs/auth @nuxtjs/axios --save

    npm install @ nuxtjs / auth @ nuxtjs / axios-保存

Once that’s done, add the code below to nuxt.config.js:

完成后,将以下代码添加到nuxt.config.js

nuxt.config.js
nuxt.config.js
modules: [
  '@nuxtjs/axios',
  '@nuxtjs/auth'
],

Next, we need to set up the modules. Paste the code below into nuxt.config.js

接下来,我们需要设置模块。 将以下代码粘贴到nuxt.config.js

nuxt.config.js
nuxt.config.js
axios: {
  baseURL: 'http://127.0.0.1:3333/api'
},

auth: {
  strategies: {
    local: {
      endpoints: {
        login: { url: 'login', method: 'post', propertyName: 'data.token' },
        user: { url: 'me', method: 'get', propertyName: 'data' },
        logout: false
      }
    }
  }
}

Here, we set the base URL (which is that of our API from earlier on) that Axios will use when making requests. Then we define the authentication endpoints for the local strategy corresponding to those on our API. On successful authentication, the token will be available in the response as a token object inside a data object, hence why we set propertyName to data.token. Similarly, the response from the /me endpoint will be inside a data object. Lastly, we set logout to false since our API doesn’t have an endpoint for logout. We’ll just remove the token from localstorage when a user logs out.

在这里,我们设置了Axios在发出请求时将使用的基本URL(这是我们以前的API的基本URL)。 然后,我们为local策略定义与API上相应的身份验证终结点。 成功认证后,令牌将作为data对象内的token对象在响应中可用,因此为什么我们将propertyName设置为data.token 。 同样, /me端点的响应将在data对象内部。 最后,由于我们的API没有用于注销的端点,因此我们将logout设置为false 。 当用户注销时,我们将从本地存储中删除令牌。

创建导航栏组件 (Creating a Navbar Component)

To style our app, we’ll be making use of Bulma. Open nuxt.config.js and paste the code below within the link object that is inside the head object:

要设计我们的应用程序样式,我们将使用Bulma 。 打开nuxt.config.js并将以下代码粘贴到head对象内部的link对象内:

nuxt.config.js
nuxt.config.js
{
    rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css'
}

Now, let’s create the Navbar component. Rename AppLogo.vue inside the components directory to Navbar.vue and replace it content with the following:

现在,让我们创建Navbar组件。 将components目录内的AppLogo.vue重命名为Navbar.vue并将其内容替换为以下内容:

components/Navbar.vue
组件/Navbar.vue
<template>
  <nav class="navbar is-light">
    <div class="container">
      <div class="navbar-brand">
        <nuxt-link class="navbar-item" to="/">Nuxt Auth</nuxt-link>
        <button class="button navbar-burger">
          <span></span>
          <span></span>
          <span></span>
        </button>
      </div>
      <div class="navbar-menu">
        <div class="navbar-end">
          <div class="navbar-item has-dropdown is-hoverable">
            <a class="navbar-link">
              My Account
            </a>
            <div class="navbar-dropdown">
              <nuxt-link class="navbar-item" to="/profile">My Profile</nuxt-link>
              <hr class="navbar-divider">
              <a class="navbar-item">Logout</a>
            </div>
          </div>
          <nuxt-link class="navbar-item" to="/register">Register</nuxt-link>
          <nuxt-link class="navbar-item" to="/login">Log In</nuxt-link>
        </div>
      </div>
    </div>
  </nav>
</template>

The Navbar component contains links to login or register, links to view profile or logout.

导航栏组件包含用于登录或注册的链接,用于查看配置文件或注销的链接。

Next, let’s update the default layout to make use of the Navbar component. Open layouts/default.vue and replace its content with the following:

接下来,让我们更新默认布局以使用Navbar组件。 打开layouts/default.vue并将其内容替换为以下内容:

layouts/default.vue
布局/ default.vue
<template>
  <div>
    <Navbar/>
    <nuxt/>
  </div>
</template>

<script>
import Navbar from '~/components/Navbar'

export default {
  components: {
    Navbar
  }
}
</script>

Also, let’s update the homepage. Open pages/index.vue and replace its content with the following:

另外,让我们更新主页。 打开pages/index.vue并将其内容替换为以下内容:

pages/index.vue
pages / index.vue
<template>
  <section class="section">
    <div class="container">
      <h1 class="title">Nuxt Auth</h1>
    </div>
  </section>
</template>

Our app should now look something similar to below:

现在,我们的应用程序应类似于以下内容:

用户注册 (User registration)

Inside the pages directory, create a new register.vue file and paste the code below in it:

pages目录中,创建一个新的register.vue文件,并将以下代码粘贴到其中:

pages/register.vue
pages / register.vue
<template>
  <section class="section">
    <div class="container">
      <div class="columns">
        <div class="column is-4 is-offset-4">
          <h2 class="title has-text-centered">Register!</h2>

          <Notification :message="error" v-if="error"/>

          <form method="post" @submit.prevent="register">
            <div class="field">
              <label class="label">Username</label>
              <div class="control">
                <input
                  type="text"
                  class="input"
                  name="username"
                  v-model="username"
                  required
                >
              </div>
            </div>
            <div class="field">
              <label class="label">Email</label>
              <div class="control">
                <input
                  type="email"
                  class="input"
                  name="email"
                  v-model="email"
                  required
                >
              </div>
            </div>
            <div class="field">
              <label class="label">Password</label>
              <div class="control">
                <input
                  type="password"
                  class="input"
                  name="password"
                  v-model="password"
                  required
                >
              </div>
            </div>
            <div class="control">
              <button type="submit" class="button is-dark is-fullwidth">Register</button>
            </div>
          </form>

          <div class="has-text-centered" style="margin-top: 20px">
            Already got an account? <nuxt-link to="/login">Login</nuxt-link>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<script>
import Notification from '~/components/Notification'

export default {
  components: {
    Notification,
  },

  data() {
    return {
      username: '',
      email: '',
      password: '',
      error: null
    }
  },

  methods: {
    async register() {
      try {
        await this.$axios.post('register', {
          username: this.username,
          email: this.email,
          password: this.password
        })

        await this.$auth.loginWith('local', {
          data: {
            email: this.email,
            password: this.password
          },
        })

        this.$router.push('/')
      } catch (e) {
        this.error = e.response.data.message
      }
    }
  }
}
</script>

This contains a form with three fields: username, email, and password. Each field is bound to a corresponding data on the component. When the form is submitted, a register method will be called. Using the Axios module, we make a post request to the /register endpoint, passing along the user data. If the registration was successful, we make use of the Auth module’s loginWith(), using the local strategy and passing the user data to log the user in. Then we redirect the user to the homepage. If there is an error during the registration, we set the error data as the error message gotten from the API response.

它包含具有三个字段的表单:用户名,电子邮件和密码。 每个字段都绑定到组件上的相应数据。 提交表单后,将调用一个register方法。 使用Axios模块,我们向/register端点发出发布请求,并传递用户数据。 如果注册成功,我们将使用Auth模块的loginWith() ,并使用local策略并传递用户数据以登录用户。然后,将用户重定向到首页。 如果在注册过程中出现错误,我们将error数据设置为从API响应中获得的错误消息。

If there is an error, the error message is displayed by a Notification component, which we’ll create shortly.

如果有错误,错误消息将由Notification组件显示,我们将在不久后创建该组件。

Before we test the user registration out, let’s create the Notification component. Create a new Notification.vue file inside components and paste the code below in it:

在测试用户注册之前,让我们创建通知组件。 在components内部创建一个新的Notification.vue文件,并将以下代码粘贴到其中:

components/Notification.vue
组件/Notification.vue
<template>
  <div class="notification is-danger">
    {{ message }}
  </div>
</template>

<script>
export default {
  name: 'Notification',
  props: ['message']
}
</script>

The Notification component accepts a message props, which is the error message.

Notification组件接受一条message props,即错误消息。

Now, we can test out user registration:

现在,我们可以测试用户注册:

显示用户是否登录 (Showing whether a user is logged in or not)

Upon successful registration, we should be logged in but there is no way for us to know whether we are logged in or not for now. So let’s fix that by updating the Navbar component and adding some computed properties.

成功注册后,我们应该已经登录,但是目前没有办法让我们知道是否登录。 因此,让我们通过更新Navbar组件并添加一些计算出的属性来解决此问题。

Before we do just that, let’s first activate the Vuex store by creating an index.js file inside the store directory. The Auth module stores user authentication status as well as user details inside Vuex state in an auth object. So we can check if a user is logged in or not with this.$store.state.auth.loggedIn, which will either return true or false. Similarly, we can get a user’s details with this.$store.state.auth.user, which will be null if no user is logged in.

在执行此操作之前,我们首先通过在store目录中创建index.js文件来激活Vuex商店。 Auth模块将用户身份验证状态以及用户详细信息存储在auth对象中的Vuex状态内。 因此,我们可以使用this.$store.state.auth.loggedIn检查用户是否登录,该用户返回truefalse 。 同样,我们可以使用this.$store.state.auth.user获取用户的详细信息,如果没有用户登录,则该this.$store.state.auth.usernull

NOTE: We can also access the user authentication status as well as the user details directly with the Auth module using this.$auth.loggedIn and this.$auth.user respectively.

注意:我们还可以分别使用this.$auth.loggedInthis.$auth.user通过Auth模块直接访问用户身份验证状态和用户详细信息。

Since we might want to use the computed properties in multiple places in our app, let’s create store getters. Paste the code below into store/index.js:

由于我们可能想在应用程序中的多个位置使用计算所得的属性,因此让我们创建商店吸气剂。 将以下代码粘贴到store/index.js

store/index.js
商店/index.js
export const getters = {
  isAuthenticated(state) {
    return state.auth.loggedIn
  },

  loggedInUser(state) {
    return state.auth.user
  }
}

Here, we create two getters. The first one (isAuthenticated) will return the authentication status of a user and the second (loggedInUser) will return the details or the logged in user.

在这里,我们创建两个吸气剂。 第一个( isAuthenticated )将返回用户的身份验证状态,第二个( loggedInUser )将返回详细信息或已登录的用户。

Next, let’s update the Navbar component to make use of the getters. Replace the content of components/Navbar.vue with the following:

接下来,让我们更新Navbar组件以利用吸气剂。 用以下内容替换components/Navbar.vue的内容:

components/Navbar.vue
组件/Navbar.vue
<template>
  <nav class="navbar is-light">
    <div class="container">
      <div class="navbar-brand">
        <nuxt-link class="navbar-item" to="/">Nuxt Auth</nuxt-link>
        <button class="button navbar-burger">
          <span></span>
          <span></span>
          <span></span>
        </button>
      </div>
      <div class="navbar-menu">
        <div class="navbar-end">
          <div class="navbar-item has-dropdown is-hoverable" v-if="isAuthenticated">
            <a class="navbar-link">
              {{ loggedInUser.username }}
            </a>
            <div class="navbar-dropdown">
              <nuxt-link class="navbar-item" to="/profile">My Profile</nuxt-link>
              <hr class="navbar-divider">
              <a class="navbar-item">Logout</a>
            </div>
          </div>
          <template v-else>
            <nuxt-link class="navbar-item" to="/register">Register</nuxt-link>
            <nuxt-link class="navbar-item" to="/login">Log In</nuxt-link>
          </template>
        </div>
      </div>
    </div>
  </nav>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters(['isAuthenticated', 'loggedInUser'])
  }
}
</script>

We create the computed properties by using the spread operator () to extract the getters from mapGetters. Then using isAuthenticated, we display the user menu or links to login or register depending on whether the user is logged in or not. Also, we use loggedInUser to display the authenticated user username.

我们通过使用散布运算符( )从mapGetters提取吸气剂来创建计算属性。 然后,使用isAuthenticated ,根据用户是否登录,显示用户菜单或用于登录或注册的链接。 另外,我们使用loggedInUser显示经过身份验证的用户名。

Now, if we give our app a refresh, we should see something similar to below:

现在,如果我们刷新应用程序,我们应该会看到类似于以下内容:

用户登录 (User log in)

Now let’s allow returning users ability to log in. Create a new login.vue file inside the pages directory and paste the code below in it:

现在,让login.vue用户能够登录。在pages目录中创建一个新的login.vue文件,并将以下代码粘贴到其中:

pages/login.vue
pages / login.vue
<template>
  <section class="section">
    <div class="container">
      <div class="columns">
        <div class="column is-4 is-offset-4">
          <h2 class="title has-text-centered">Welcome back!</h2>

          <Notification :message="error" v-if="error"/>

          <form method="post" @submit.prevent="login">
            <div class="field">
              <label class="label">Email</label>
              <div class="control">
                <input
                  type="email"
                  class="input"
                  name="email"
                  v-model="email"
                >
              </div>
            </div>
            <div class="field">
              <label class="label">Password</label>
              <div class="control">
                <input
                  type="password"
                  class="input"
                  name="password"
                  v-model="password"
                >
              </div>
            </div>
            <div class="control">
              <button type="submit" class="button is-dark is-fullwidth">Log In</button>
            </div>
          </form>
          <div class="has-text-centered" style="margin-top: 20px">
            <p>
              Don't have an account? <nuxt-link to="/register">Register</nuxt-link>
            </p>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<script>
import Notification from '~/components/Notification'

export default {
  components: {
    Notification,
  },

  data() {
    return {
      email: '',
      password: '',
      error: null
    }
  },

  methods: {
    async login() {
      try {
        await this.$auth.loginWith('local', {
          data: {
            email: this.email,
            password: this.password
          }
        })

        this.$router.push('/')
      } catch (e) {
        this.error = e.response.data.message
      }
    }
  }
}
</script>

This is quite similar to the register page. The form contains two fields: email and password. When the form is submitted, a login method will be called. Using the Auth module loginWith() and passing along the user data, we log the user in. If the authentication was successful, we redirect the user to the homepage. Otherwise set error to the error message gotten from the API response. Again, we are using the Notification component from earlier on to display the error message.

这与register页面非常相似。 该表格包含两个字段:电子邮件和密码。 提交表单后,将调用login方法。 使用Auth模块loginWith()并传递用户数据,我们使用户登录。如果身份验证成功,则将用户重定向到主页。 否则,将error设置为从API响应获得的错误消息。 同样,我们从较早开始就使用Notification组件显示错误消息。

显示用户个人资料 (Displaying the user profile)

Let’s allow logged in users to view their profile. Create a new profile.vue file inside the pages directory and paste the code below in it:

让我们允许登录的用户查看其个人资料。 在pages目录中创建一个新的profile.vue文件,并将以下代码粘贴到其中:

pages/profile.vue
pages / profile.vue
<template>
  <section class="section">
    <div class="container">
      <h2 class="title">My Profile</h2>
      <div class="content">
        <p>
          <strong>Username:</strong>
          {{ loggedInUser.username }}
        </p>
        <p>
          <strong>Email:</strong>
          {{ loggedInUser.email }}
        </p>
      </div>
    </div>
  </section>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters(['loggedInUser'])
  }
}
</script>

We are using the loggedInUser getter from earlier on to display display the user details.

我们从较早开始就使用了loggedInUser getter来显示用户详细信息。

Clicking on the My Profile link should result in a My Profile page being displayed.

单击“ 我的个人资料”链接应导致显示“ 我的个人资料”页面。

注销用户 (Logging Users Out)

Update the logout link inside the Navbar component as below:

更新导航栏组件内的注销链接,如下所示:

components/Navbar.vue
组件/Navbar.vue
<a class="navbar-item" @click="logout">Logout</a>

When the logout link is click, it will trigger a logout method.

单击注销链接时,将触发logout方法。

Next, let’s add the logout method inside the script section of the Navbar component:

接下来,让我们在Navbar组件的脚本部分内添加logout方法:

components/Navbar.vue
组件/Navbar.vue
methods: {
  async logout() {
    await this.$auth.logout();
  },
},

We call the logout() of the Auth module. This will delete the user’s token from localstorage and redirect the user to the homepage.

我们调用Auth模块的logout() 。 这将从本地存储中删除用户的令牌,并将用户重定向到主页。

限制个人资料页面 (Restricting the Profile Page)

As it stands now, anybody can visit the profile page and if the user is not logged in, it will result in error.

目前,任何人都可以访问profile页面,如果用户未登录,将导致错误。

To fix this, we need to restrict the profile page to only logged in users. Luckily for us, we can achieve that with the Auth module. The Auth module comes with an auth middleware, which we can use in this scenario.

要解决此问题,我们需要将个人资料页面限制为仅已登录的用户。 幸运的是,我们可以使用Auth模块来实现。 Auth模块附带一个auth中间件,我们可以在这种情况下使用它。

So let’s add the auth middleware to the profile page, update the script section as below:

因此,让我们将auth中间件添加到profile页面,如下更新脚本部分:

pages/profile.vue
pages / profile.vue
<script>
...

export default {
  middleware: 'auth',
 ...
}
</script>

Now when a user that is not logged in tries to visit the profile page, the user will be redirected to the login page.

现在,当未登录的用户尝试访问profile页面时,该用户将被重定向到login页面。

创建访客中间件 (Creating a Guest Middleware)

Again as it stand, even as a logged in user, we can still access the login and register pages. One way to fix that is to restrict login and register pages to only users that are not logged in. We can do that by creating a guest middleware. Inside the middleware directory, create a new guest.js file and paste the code below in it:

照原样,即使作为登录用户,我们仍然可以访问登录页面和注册页面。 一种解决方法是将登录和注册页面限制为仅未登录的用户。我们可以通过创建来宾中间件来做到这一点。 在middleware目录中,创建一个新的guest.js文件,并将以下代码粘贴到其中:

middleware/guest.js
中间件/guest.js
export default function ({ store, redirect }) {
  if (store.state.auth.loggedIn) {
    return redirect('/')
  }
}

A middleware accepts the context as its first argument. So we extract store and redirect from the context. We check if the user is logged in then redirect the user to the homepage. Otherwise, we allow the normal execution of the request.

中间件接受上下文作为其第一个参数。 因此,我们提取store并从上下文redirect 。 我们检查用户是否已登录,然后将用户重定向到主页。 否则,我们将允许请求的正常执行。

Next, let’s make use of this middleware. Update the script section of both login and register as below:

接下来,让我们利用这个中间件。 更新loginregister的脚本部分,如下所示:

<script>
...

export default {
  middleware: 'guest',
 ...
}
</script>

Now everything will be working as expected.

现在一切都会按预期进行。

结论 (Conclusion)

In this tutorial, we looked at how to implement authentication in a Nuxt.js application using the Auth module. We also saw how to keep the authentication flow sleek by making use of middleware.

在本教程中,我们研究了如何使用Auth模块在Nuxt.js应用程序中实现身份验证。 我们还看到了如何通过使用中间件来保持认证流程的流畅。

To learn more and the Auth module, checkout the docs.

要了解更多信息和Auth模块,请查看docs

翻译自: https://www.digitalocean.com/community/tutorials/implementing-authentication-in-nuxtjs-app

nuxt.js 全局 js

 类似资料: