我从github获得了node.js登录/注册API,我创建了客户端来访问端点。我收到Cookie无效的错误,我猜它没有被创建。 这是我的node.js代码
server.js
const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
const { getSecret } = require('./secrets');
const usersRoute = require('./routes/users');
mongoose.Promise = global.Promise;
mongoose.connect(getSecret('dbUri')).then(
() => {
console.log('Connected to mongoDB');
},
(err) => console.log('Error connecting to mongoDB', err)
);
const app = express();
const port = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use(cookieParser());
app.use(usersRoute);
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
module.exports = { app };
下面是user.js代码
user.js
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const bcrypt = require('bcryptjs');
const UserSchema = new mongoose.Schema({
company: {
name: '',
type: ''
},
name:{
type: String,
required: true,
trim: true,
},
email: {
type: String,
required: true,
minlength: 1,
trim: true,
unique: true,
},
password: {
type: String,
required: true,
minlength: 6,
},
});
UserSchema.plugin(uniqueValidator);
UserSchema.pre('save', function(next) {
let user = this;
if (!user.isModified('password')) {
return next();
}
bcrypt
.genSalt(12)
.then((salt) => {
return bcrypt.hash(user.password, salt);
})
.then((hash) => {
user.password = hash;
next();
})
.catch((err) => next(err));
});
module.exports = mongoose.model('User', UserSchema);
这是一个users.js代码
users.js
const express = require('express');
const bcrypt = require('bcryptjs');
const User = require('../models/user');
const Session = require('../models/session');
const { authenticate } = require('../middleware/authenticate');
const { csrfCheck } = require('../middleware/csrfCheck');
const { initSession, isEmail } = require('../utils/utils');
const router = express.Router();
router.post('/api/auth/register', async (req, res) => {
try {
const { company, name, email, password } = req.body;
if (!isEmail(email)) {
throw new Error('Email must be a valid email address.');
}
if (typeof password !== 'string') {
throw new Error('Password must be a string.');
}
const user = new User({company, name, email, password });
const persistedUser = await user.save();
const userId = persistedUser._id;
const session = await initSession(userId);
res
.cookie('token', session.token, {
httpOnly: true,
sameSite: true,
maxAge: 1209600000,
secure: process.env.NODE_ENV === 'production',
})
.status(201)
.json({
title: 'User Registration Successful',
detail: 'Successfully registered new user',
csrfToken: session.csrfToken,
});
} catch (err) {
res.status(400).json({
errors: [
{
title: 'Registration Error',
detail: 'Something went wrong during registration process.',
errorMessage: err.message,
},
],
});
}
});
router.post('/api/auth/login', async (req, res) => {
try {
const { email, password } = req.body;
if (!isEmail(email)) {
return res.status(400).json({
errors: [
{
title: 'Bad Request',
detail: 'Email must be a valid email address',
},
],
});
}
if (typeof password !== 'string') {
return res.status(400).json({
errors: [
{
title: 'Bad Request',
detail: 'Password must be a string',
},
],
});
}
const user = await User.findOne({ email });
if (!user) {
throw new Error();
}
const userId = user._id;
const passwordValidated = await bcrypt.compare(password, user.password);
if (!passwordValidated) {
throw new Error();
}
const session = await initSession(userId);
res
.cookie('token', session.token, {
httpOnly: true,
sameSite: true,
maxAge: 1209600000,
secure: process.env.NODE_ENV === 'production',
})
.json({
title: 'Login Successful',
detail: 'Successfully validated user credentials',
csrfToken: session.csrfToken,
});
} catch (err) {
res.status(401).json({
errors: [
{
title: 'Invalid Credentials',
detail: 'Check email and password combination',
errorMessage: err.message,
},
],
});
}
});
router.get('/api/auth/detail', authenticate, async (req, res) => {
try {
const { userId } = req.session;
const user = await User.findById({ _id: userId }, { email: 1, _id: 0 });
res.json({
title: 'Authentication successful',
detail: 'Successfully authenticated user',
user,
});
} catch (err) {
res.status(401).json({
errors: [
{
title: 'Unauthorized',
detail: 'Not authorized to access this route',
errorMessage: err.message,
},
],
});
}
});
router.delete('/me', authenticate, csrfCheck, async (req, res) => {
try {
const { userId } = req.session;
const { password } = req.body;
if (typeof password !== 'string') {
throw new Error();
}
const user = await User.findById({ _id: userId });
const passwordValidated = await bcrypt.compare(password, user.password);
if (!passwordValidated) {
throw new Error();
}
await Session.expireAllTokensForUser(userId);
res.clearCookie('token');
await User.findByIdAndDelete({ _id: userId });
res.json({
title: 'Account Deleted',
detail: 'Account with credentials provided has been successfuly deleted',
});
} catch (err) {
res.status(401).json({
errors: [
{
title: 'Invalid Credentials',
detail: 'Check email and password combination',
errorMessage: err.message,
},
],
});
}
});
router.put('/logout', authenticate, csrfCheck, async (req, res) => {
try {
const { session } = req;
await session.expireToken(session.token);
res.clearCookie('token');
res.json({
title: 'Logout Successful',
detail: 'Successfuly expired login session',
});
} catch (err) {
res.status(400).json({
errors: [
{
title: 'Logout Failed',
detail: 'Something went wrong during the logout process.',
errorMessage: err.message,
},
],
});
}
});
module.exports = router;
authentication.js 代码在此处
const User = require('../models/user');
const Session = require('../models/session');
const authenticate = async (req, res, next) => {
try {
const token = req.cookies;
if (typeof token !== 'string') {
throw new Error('Request cookie is invalid.');
}
const session = await Session.findOne({ token, status: 'valid' });
if (!session) {
res.clearCookie('token');
throw new Error('Your session has expired. You need to log in.');
}
req.session = session;
next();
} catch (err) {
res.status(401).json({
errors: [
{
title: 'Unauthorized',
detail: 'Authentication credentials invalid',
errorMessage: err.message,
},
],
});
}
};
module.exports = { authenticate };
secret.js 代码看起来像这样
const secrets = {
dbUri: process.env.DB_URI || 'mongodb://localhost/databaseName',
};
const getSecret = (key) => secrets[key];
module.exports = { getSecret };
我也有看起来像这样的session.js代码
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const crypto = require('crypto');
const SessionSchema = new mongoose.Schema({
token: {
type: String,
unique: true,
required: true,
},
csrfToken: {
type: String,
unique: true,
required: true,
},
createdAt: {
type: Date,
default: Date.now,
},
userId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
},
status: {
type: String,
enum: ['valid', 'expired'],
default: 'valid',
},
});
SessionSchema.plugin(uniqueValidator);
SessionSchema.statics.generateToken = function() {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
reject(err);
}
const token = buf.toString('hex');
resolve(token);
});
});
};
SessionSchema.statics.expireAllTokensForUser = function(userId) {
return this.updateMany({ userId }, { $set: { status: 'expired' } });
};
SessionSchema.methods.expireToken = function() {
const session = this;
return session.update({ $set: { status: 'expired' } });
};
module.exports = mongoose.model('Session', SessionSchema);
我不确定遵循端点API编码所需的所有内容后,为什么会收到消息错误。任何帮助我都会非常感激。谢谢