Udemy - Nuxt JS with Laravel API - Building SSR Vue JS Apps 笔记11 Nuxt - Authentication

Nuxt Auth Setup

参考  https://auth.nuxtjs.org/#getting-started

执行:

npm install @nuxtjs/auth @nuxtjs/axios

nuxt.config.js修改:

export default {
  mode: 'universal',
  /*
  ** Headers of the page
  */
  head: {
    title: process.env.npm_package_name || '',
    meta: [
      {charset: 'utf-8'},
      {name: 'viewport', content: 'width=device-width, initial-scale=1'},
      {hid: 'description', name: 'description', content: process.env.npm_package_description || ''}
    ],
    link: [
      {rel: 'icon', type: 'image/x-icon', href: '/favicon.ico'},
      {rel: 'stylesheet', href: 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css'},
    ],
    script: [
      {src: 'https://code.jquery.com/jquery-3.5.1.slim.min.js', type: 'text/javascript'},
      {src: 'https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js', type: 'text/javascript'},
      {src: 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js', type: 'text/javascript'},
    ]
  },
  /*
  ** Customize the progress-bar color
  */
  loading: {color: '#fff'},
  /*
  ** Global CSS
  */
  css: [
    '@/assets/styles/main.css',
  ],
  /*
  ** Plugins to load before mounting the App
  */
  plugins: [],
  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [],
  /*
  ** Nuxt.js modules
  */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/auth',
  ],
  /*
  ** Axios module configuration
  ** See https://axios.nuxtjs.org/options
  */
  axios: {
    baseURL: "http://backend.test/api",
  },
  /*
  ** Build configuration
  */
  build: {
    /*
    ** You can extend webpack config here
    */
    extend(config, ctx) {
    }
  },
  auth: {
    // Options
  }
}


批注 2020-05-15 130048

然后参考https://auth.nuxtjs.org/schemes/local.html#options 设置nuxt.config.js中的 auth option

批注 2020-05-15 130415

官方文档中有

批注 2020-05-15 131417

最为官方推荐的最佳实践,加上还是可以的。

export default {
  mode: 'universal',
  /*
  ** Headers of the page
  */
  head: {
    title: process.env.npm_package_name || '',
    meta: [
      {charset: 'utf-8'},
      {name: 'viewport', content: 'width=device-width, initial-scale=1'},
      {hid: 'description', name: 'description', content: process.env.npm_package_description || ''}
    ],
    link: [
      {rel: 'icon', type: 'image/x-icon', href: '/favicon.ico'},
      {rel: 'stylesheet', href: 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css'},
    ],
    script: [
      {src: 'https://code.jquery.com/jquery-3.5.1.slim.min.js', type: 'text/javascript'},
      {src: 'https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js', type: 'text/javascript'},
      {src: 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js', type: 'text/javascript'},
    ]
  },
  /*
  ** Customize the progress-bar color
  */
  loading: {color: '#fff'},
  /*
  ** Global CSS
  */
  css: [
    '@/assets/styles/main.css',
  ],
  /*
  ** Plugins to load before mounting the App
  */
  plugins: [],
  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [],
  /*
  ** Nuxt.js modules
  */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/auth',
  ],
  /*
  ** Axios module configuration
  ** See https://axios.nuxtjs.org/options
  */
  axios: {
    baseURL: "http://backend.test/api",
  },
  /*
  ** Build configuration
  */
  build: {
    /*
    ** You can extend webpack config here
    */
    extend(config, ctx) {
    }
  },
  auth: {
    // Options
    strategies: {
      local: {
        endpoints: {
          login: {url: 'login', method: 'post', propertyName: 'meta.token'},
          user: {url: 'user', method: 'get', propertyName: 'data'},
          logout: {url: 'logout', method: 'post'},
        }
      }
    }
  }
}

添加store/index.js文件,代码暂时留空。

User Login – Nuxt

修改login.vue:

<template>
  <div class="container col-md-6 mt-5">
    <h2>Login</h2>
    <br>
    <form @submit.prevent="submit">
      <div class="form-group">
        <label>Email address</label>
        <input type="email" class="form-control" v-model.trim="form.email" autofocus>
        <small class="form-text text-danger">Show errors here</small>
      </div>
      <div class="form-group">
        <label>Password</label>
        <input type="password" class="form-control" v-model.trim="form.password" autofocus>
        <small class="form-text text-danger">Show errors here</small>
      </div>
      <button type="submit" class="btn btn-primary">Login</button>
    </form>
    <br>
    <p>Don't have an account?
      <nuxt-link to="/register">Register</nuxt-link>
    </p>
  </div>
</template>

<script>
  export default {
    name: "login",
    data() {
      return {
        form: {
          email: '',
          password: '',
        }
      }
    },
    methods: {
      async submit() {
        await this.$auth.loginWith('local', {
          data: this.form,
        });
        this.$router.push('/');
      },
    }

  }
</script>

<style scoped>

</style>

打开 http://localhost:3000/login 测试登录:

可以看到 发起了login request

批注 2020-05-15 132402

以及一个user request

批注 2020-05-15 132443

而vuex中状态:

批注 2020-05-15 132531

有了一个auth Object, loggedIn也为true,user也有一个Object了。

local storage中的strategy值为true,可以看到auth_token也存储好了。

批注 2020-05-15 132720

在其请求user的时候,会自动配置Bearer token:

批注 2020-05-15 133002

尝试清空site data

批注 2020-05-15 133154

然后刷新页面,查看vuex状态:

批注 2020-05-15 133250

user object清空了,loggedIn也变成了false。

未清空site data的话,刷新会是这样的:

批注 2020-05-15 133541

Auth Getters

修改store/index.js文件:

export const getters = {
  authenticated(state) {
    return state.auth.loggedIn;
  },

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

Navbar.vue中获取auth状态判断是否展示login register按钮;

测试一下:


<template>
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <nuxt-link to="/" class="navbar-brand">Frontend</nuxt-link>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
            aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav">
        <li class="nav-item active">
          <nuxt-link class="nav-link" to="/">Home</nuxt-link>
        </li>
        <li class="nav-item">
          <nuxt-link class="nav-link" to="/">Posts</nuxt-link>
        </li>
      </ul>
      <ul class="navbar-nav ml-auto">
        <li class="nav-item">
          <nuxt-link class="nav-link" to="/login">Login</nuxt-link>
        </li>
        <li class="nav-item">
          <nuxt-link class="nav-link" to="/register">Register</nuxt-link>
        </li>
      </ul>
    </div>
    {{loggedIn}}
  </nav>
</template>

<script>
  import {mapGetters} from 'vuex';

  export default {
    name: "Navbar",
    computed: {
      ...mapGetters({
        loggedIn: "authenticated",
      })
    }
  }
</script>

<style scoped>

</style>

结果:

批注 2020-05-15 141424

测试完效果后,删除

批注 2020-05-15 141546

Global Mixin

新建plugins/mixins/user.js

import Vue from 'vue';
import {mapGetters} from 'vuex';

const User = {
  install(Vue, options) {
    Vue.mixin({
      computed: {
        ...mapGetters({
          user: 'user',
          authenticated: "authenticated",
        })
      }
    })
  }
};
Vue.use(User);

然后再nuxt.config.js中注册这个plugin

批注 2020-05-15 142021

因为mixin注册好了,所以npm run dev 之后我们就可以使用了。

再在Navbar.vue中测试一下:

批注 2020-05-15 142312

Show User

修改Navbar.vue:

<template>
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <nuxt-link to="/" class="navbar-brand">Frontend</nuxt-link>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
            aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav">
        <li class="nav-item active">
          <nuxt-link class="nav-link" to="/">Home</nuxt-link>
        </li>
        <li class="nav-item">
          <nuxt-link class="nav-link" to="/">Posts</nuxt-link>
        </li>
      </ul>
      <template v-if="!authenticated">
        <ul class="navbar-nav ml-auto">
          <li class="nav-item">
            <nuxt-link class="nav-link" to="/login">Login</nuxt-link>
          </li>
          <li class="nav-item">
            <nuxt-link class="nav-link" to="/register">Register</nuxt-link>
          </li>
        </ul>
      </template>
      <template v-else>
        <ul class="navbar-nav ml-auto">
          <li class="nav-item">
            <a class="nav-link">{{user.name}}</a>
          </li>
          <li class="nav-item">
            <a class="nav-link">Logout</a>
          </li>
        </ul>
      </template>
    </div>

  </nav>
</template>

<script>

  export default {
    name: "Navbar",

  }
</script>

<style scoped>

</style>

批注 2020-05-15 142814

user是mixin中已经全局注册了的,所以直接可以使用。

Logout User

在Navbar.vue中添加:

批注 2020-05-15 143354

点击logout前:

批注 2020-05-15 143540

点击logout

批注 2020-05-15 143625

批注 2020-05-15 143649

批注 2020-05-15 143727

批注 2020-05-15 143843

User Register – Nuxt

修改pages/register.vue:

<template>
  <div class="container col-md-6 mt-5">
    <h2>Register</h2>
    <br>
    <form @submit.prevent="submit">
      <div class="form-group">
        <label>UserName</label>
        <input type="text" class="form-control" placeholder="Enter your Username" v-model.trim="form.name" autofocus>
        <small class="form-text text-danger">Show errors here</small>
      </div>
      <div class="form-group">
        <label>Email address</label>
        <input type="email" class="form-control" placeholder="Enter your email address" v-model.trim="form.email">
        <small class="form-text text-danger">Show errors here</small>
      </div>
      <div class="form-group">
        <label>Password</label>
        <input type="password" class="form-control" placeholder="Enter your password" v-model.trim="form.password">
        <small class="form-text text-danger">Show errors here</small>
      </div>
      <div class="form-group">
        <label>Confirm Password</label>
        <input type="password" class="form-control" placeholder="Confirm your password"
               v-model.trim="form.password_confirmation">
        <small class="form-text text-danger">Show errors here</small>
      </div>
      <button type="submit" class="btn btn-primary">Register</button>
    </form>
    <br>
    <p>Already have an account?
      <nuxt-link to="/login">Login</nuxt-link>
    </p>
  </div>
</template>

<script>
  export default {
    name: "register",
    data() {
      return {
        form: {
          name: '',
          email: '',
          password: '',
          password_confirmation: '',
        }
      }
    },
    methods: {
      async submit() {
        await this.$axios.$post('register', this.form);

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

        //redirect
        this.$router.push('/');
      }
    }
  }
</script>

<style scoped>

</style>

效果如下:

nuxt-register

源代码:https://github.com/dzkjz/laravel-backend-nuxt-frontend-frontpart

选择:

批注 2020-05-15 150552

posted @ 2020-05-15 14:41  dzkjz  阅读(54)  评论(0)    收藏  举报