问题
I am attempting to build a basic login/registration app using Vue, Express, Node, and MongoDB. I have been successful in setting up the Express router to enable registration and logging in of users, with basic user info stored in MongoDB. I am attempting to return user data back to the screen after logging in. So far, I have set up router.get() in Express to return the username of all users back to the screen. However, I want to configure the axios.get() method in Vue.js to return only the username of the logged in user, as opposed to all the user names stored in MongoDB. Normally in Firebase I would use something like let snapshot = await ref.where('userid', '==', firebase.auth().currentUser.uid).get() to send back info exclusively about the current user. How can I set up my axios.get() method to execute something similar? My code is below:
logged in page
<template>
<b-row>
<b-col cols="12">
<h2>
You are now logged in!
<b-link @click="logout()">(Logout)</b-link>
</h2>
<table style="width:100%">
<tr>
<th>User Names</th>
</tr>
<tr v-for="user in users" :key="user._id">
<td>{{ user.username }}</td>
</tr>
</table>
<ul v-if="errors && errors.length">
<li v-for="error of errors" :key="error._id">
<b-alert show>{{error.message}}</b-alert>
</li>
</ul>
</b-col>
</b-row>
</template>
<script>
import axios from 'axios'
export default {
name: 'BookList',
data () {
return {
users: [],
errors: []
}
},
created () {
axios.defaults.headers.common['Authorization'] = localStorage.getItem('jwtToken')
axios.get(`http://localhost:3000/api/auth`)
.then(response => {
this.users = response.data
})
},
methods: {
logout () {
localStorage.removeItem('jwtToken')
this.$router.push({
name: 'Login'
})
}
}
}
</script>
GET route in Express
router.get('/', function(req, res) {
User.find(function (err, products) {
if (err) return next(err);
res.json(products);
});
});
User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcryptjs');
var UserSchema = new Schema({
username: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
}
});
UserSchema.pre('save', function (next) {
var user = this;
if (this.isModified('password') || this.isNew) {
bcrypt.genSalt(10, function (err, salt) {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, null, function (err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
});
});
} else {
return next();
}
});
UserSchema.methods.comparePassword = function (passw, cb) {
bcrypt.compare(passw, this.password, function (err, isMatch) {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
};
module.exports = mongoose.model('User', UserSchema);
Register route
router.post('/register', function(req, res) {
if (!req.body.username || !req.body.password) {
res.json({success: false, msg: 'Please pass username and password.'});
} else {
var newUser = new User({
username: req.body.username,
password: req.body.password
});
// save the user
newUser.save(function(err) {
if (err) {
return res.json({success: false, msg: 'Username already exists.'});
}
res.json({success: true, msg: 'Successful created new user.'});
});
}
});
回答1:
I assume your user model has username and password fields, and your password is encrypted in db.
For finding user with username, if user found comparing the user.password with the encrypted password in the request body. If user not found, or passwords not match, I send 400-Bad Request.
const bcrypt = require("bcryptjs");
..
router.post('/', async (req, res) => {
const { username, password } = req.body;
if (!(username && password))
return res.status(400).json({ error: "username and password are required" });
try {
let user = await User.findOne({ username });
if (!user) return res.status(400).json({ error: "invalid login" });
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) return res.status(400).json({ error: "invalid login" });
user.password = undefined;
res.json(user);
} catch (err) {
console.log(err);
return next(err);
}
});
To hash the password before saving the user, can you add this code to the user model?
UserSchema.pre('save', async function (next) {
this.password = await bcrypt.hash(this.password, 12);
next();
});
Register route:
router.post('/register', async (req, res) => {
const { username, password } = req.body;
if (!username || !password)
return res.json({ success: false, msg: 'Please pass username and password.' });
try {
let user = await User.findOne({ username });
if (user) return res.json({ success: false, msg: 'Username already exists.' });
user = new User({ username, password });
await user.save();
res.json({ success: true, msg: 'Successful created new user.' });
} catch (err) {
console.log(err);
res.json({ success: false, msg: 'Something went bad' });
}
});
来源:https://stackoverflow.com/questions/58347756/how-to-return-current-user-information-from-mongodb-in-a-mevn-stack-app