Я пытаюсь создать интерфейс аутентификации с помощью Vue.js, Node, Express и MongoDB.До сих пор я успешно включал регистрацию пользователей, когда имя, адрес электронной почты и пароль помещались в базу данных MongoDB при использовании пакета bcrypt для шифрования пароля.Сейчас я пытаюсь разрешить пользователю войти в систему, настроив 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.vue
.Может ли быть проблема с охранником маршрута внизу router.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