如何解决MEVN堆栈身份验证应用程序中的路由问题

时间:2019-09-19 19:37:50

标签: javascript node.js mongodb express vue.js

我正在尝试使用Vue.js,Node,Express和MongoDB构建身份验证接口。到目前为止,我已经成功启用了用户注册,使用bcrypt包对密码进行加密时,将姓名,电子邮件和密码推送到MongoDB数据库中。我现在尝试通过在users.post('/login', (req, res) => {}中设置users.js来使用户登录,以比较登录页面上输入的电子邮件和密码与数据库中存储的电子邮件和密码。如果有效,则以payload的形式返回token,然后将其推入localStorage中。由于导航栏控制过渡以反映正在登录,因此登录似乎有效。但是,屏幕不会重新路由到Profile.vue。而是,屏幕保留在Login.vue上,并且控制台上显示一条错误消息,内容为uncaught (in promise) undefined。我已将问题缩小到router.push({ name: 'Profile })中的Login.vue。换句话说,错误似乎源于此行。当我删除它时,错误消失了,但是显然我仍然需要这种行才能重新路由到Profile.vuerouter.js底部的路由防护器可能会出现问题吗?关于如何为此应用程序正确设置路由保护的任何建议?我的代码如下。谢谢!

Login.vue

<template>
    <div class="container">
        <div class="row">
            <div class="col-md-6 mt-5 mx-auto">
                <form v-on:submit.prevent="login">
                    <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
                    <div class="form-group">
                        <label for="email">Email Address</label>
                        <input type="email" v-model="email" class="form-control" name="email" placeholder="Enter Email">
                    </div>
                    <div class="form-group">
                        <label for="password">Password</label>
                        <input type="password" v-model="password" class="form-control" name="password" placeholder="Enter Password">
                    </div>
                    <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
import axios from 'axios'
import router from '../router'
import EventBus from './EventBus'

export default {
  data () {
    return {
      email: '',
      password: ''
    }
  },

  methods: {
    async login () {
      let res = await axios.post('http://localhost:5000/users/login', {
        email: this.email,
        password: this.password
      })
        await localStorage.setItem('usertoken', res.data)
        router.push({ name: 'Profile' })
        this.email = ''
        this.password = ''
        this.emitMethod()
    },
    emitMethod () {
      EventBus.$emit('logged-in', 'loggedin')
    }
  }
}
</script>

Profile.vue

<template>
    <div class="container">
        <div class="jumbotron mt-5">
            <div class="col-sm-8 mx-auto">
                <h1 class="text-center">PROFILE</h1>
            </div>
            <table class="table col-md-6 mx-auto">
                <tbody>
                    <tr>
                        <td>First Name</td>
                        <td>{{first_name}}</td>
                    </tr>
                    <tr>
                        <td>Last Name</td>
                        <td>{{last_name}}</td>
                    </tr>
                    <tr>
                        <td>Email</td>
                        <td>{{email}}</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</template>

<script>
import jwtDecode from 'jwt-decode'

export default {
  data () {
    return {
      first_name: '',
      last_name: '',
      email: ''
    }
  },
  created () {
    const token = localStorage.usertoken
    const decoded = jwtDecode(token)
    this.first_name = decoded.first_name,
    this.last_name = decoded.last_name,
    this.email = decoded.email
  }
}
</script>

users.js

const express = require("express")
const users = express.Router()
const cors = require("cors")
const jwt = require("jsonwebtoken")
const bcrypt = require("bcrypt")

const User = require("../models/User")
users.use(cors())

process.env.SECRET_KEY = 'secret'

users.post("/register", (req, res) => {
    const today = new Date()
    const userData = {
        first_name: req.body.first_name,
        last_name: req.body.last_name,
        email: req.body.email,
        password: req.body.password,
        created: today
    }

    User.findOne({
        email: req.body.email
    })
        .then(user => {
            if (!user) {
                bcrypt.hash(req.body.password, 10, (err, hash) => {
                    userData.password = hash
                    User.create(userData)
                        .then(user => {
                            res.json({ status: user.email + ' registered' })
                        })
                        .catch(err => {
                            res.send('error: ' + err)
                        })
                })
            } else {
                res.json({ error: 'User already exists' })
            }
        })
        .catch(err => {
            res.send('error: ' + err)
        })
})

users.post('/login', (req, res) => {
    User.findOne({
        email: req.body.email
    })
        .then(user => {
            if (user) {
                if (bcrypt.compareSync(req.body.password, user.password)) {
                    const payload = {
                        _id: user._id,
                        first_name: user.first_name,
                        last_name: user.last_name,
                        email: user.email
                    }
                    let token = jwt.sign(payload, process.env.SECRET_KEY, {
                        expiresIn: 1440
                    })
                    res.send(token)
                } else {
                    res.json({ error: 'User does not exist' })
                }
            } else {
                res.json({ error: 'User does not exist' })
            }
        })
        .catch(err => {
            res.send('error: ' + err)
        })
})

module.exports = users

router.js

import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/components/Login'
import Register from '@/components/Register'
import Profile from '@/components/Profile'

Vue.use(Router)

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/register',
      name: 'Register',
      component: Register
    },
    {
      path: '/profile',
      name: 'Profile',
      component: Profile,
      meta: {
        requiresAuth: true
      }
    }
  ]
})

router.beforeEach((to, from, next) => {
  const isLoggedIn = localStorage.getItem("token")
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth)
  if (requiresAuth && !isLoggedIn) next('login')
  else if (!requiresAuth && isLoggedIn) next('profile')
  else next()
})

export default router

0 个答案:

没有答案