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 } }
然后参考https://auth.nuxtjs.org/schemes/local.html#options 设置nuxt.config.js中的 auth option
官方文档中有
最为官方推荐的最佳实践,加上还是可以的。
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
以及一个user request
而vuex中状态:
有了一个auth Object, loggedIn也为true,user也有一个Object了。
local storage中的strategy值为true,可以看到auth_token也存储好了。
在其请求user的时候,会自动配置Bearer token:
尝试清空site data
然后刷新页面,查看vuex状态:
user object清空了,loggedIn也变成了false。
未清空site data的话,刷新会是这样的:
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>
结果:
测试完效果后,删除
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
因为mixin注册好了,所以npm run dev 之后我们就可以使用了。
再在Navbar.vue中测试一下:
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>
user是mixin中已经全局注册了的,所以直接可以使用。
Logout User
在Navbar.vue中添加:
点击logout前:
点击logout
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>
效果如下:
源代码:https://github.com/dzkjz/laravel-backend-nuxt-frontend-frontpart
选择: