主题
登录与用户中心
在本章节中,我们将通过构建一个简单的登录与用户中心系统,介绍如何在 Express 中实现用户身份认证、登录状态管理以及用户信息的查看与修改。我们将使用 Passport.js 来处理用户认证,JWT 用于会话管理,并且实现基本的用户信息存储与管理。
1. 安装依赖
首先,您需要安装用于处理身份认证和用户登录的必要依赖:
bash
npm install passport passport-local jsonwebtoken bcryptjs
- passport:用于处理身份验证的中间件。
- passport-local:实现本地用户名和密码认证策略。
- jsonwebtoken (JWT):用于创建和验证 JSON Web Tokens,用于会话管理。
- bcryptjs:用于加密和验证用户密码。
2. 设置 Passport.js 认证
2.1 用户模型设计
我们将使用 Mongoose 来创建一个用户模型,包含用户名、密码、邮箱和注册时间等基本信息。
js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// 创建用户模型
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
createdAt: { type: Date, default: Date.now },
});
// 加密密码
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) return next();
this.password = await bcrypt.hash(this.password, 10);
next();
});
// 比较密码
userSchema.methods.comparePassword = function (candidatePassword) {
return bcrypt.compare(candidatePassword, this.password);
};
const User = mongoose.model('User', userSchema);
module.exports = User;
2.2 配置 Passport.js
我们将使用 Passport 的 local strategy 来处理用户名和密码的身份验证。
js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User');
// 配置 Passport 本地策略
passport.use(new LocalStrategy(
async (username, password, done) => {
try {
const user = await User.findOne({ username });
if (!user) return done(null, false, { message: 'Incorrect username' });
const isMatch = await user.comparePassword(password);
if (!isMatch) return done(null, false, { message: 'Incorrect password' });
return done(null, user);
} catch (err) {
return done(err);
}
}
));
// 序列化用户
passport.serializeUser((user, done) => {
done(null, user.id);
});
// 反序列化用户
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id);
done(null, user);
} catch (err) {
done(err);
}
});
3. 用户注册与登录路由
3.1 用户注册
用户需要提供用户名、邮箱和密码来注册。我们将使用 POST 请求处理注册,并在数据库中保存用户信息。
js
const express = require('express');
const User = require('../models/User');
const passport = require('passport');
const router = express.Router();
// 注册路由
router.post('/register', async (req, res) => {
const { username, email, password } = req.body;
try {
const existingUser = await User.findOne({ username });
if (existingUser) return res.status(400).json({ message: 'Username already taken' });
const newUser = new User({ username, email, password });
await newUser.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (err) {
res.status(500).json({ message: 'Error registering user', error: err });
}
});
3.2 用户登录
用户可以使用用户名和密码进行登录,成功后返回一个 JWT,用于后续的请求认证。
js
const jwt = require('jsonwebtoken');
// 登录路由
router.post('/login', passport.authenticate('local', { session: false }), (req, res) => {
const user = req.user;
// 生成 JWT
const token = jwt.sign({ id: user.id, username: user.username }, 'secretKey', { expiresIn: '1h' });
res.status(200).json({
message: 'Login successful',
token: token,
user: {
id: user.id,
username: user.username,
email: user.email,
}
});
});
3.3 用户中心
登录后,用户可以通过访问用户中心查看和修改个人信息。我们通过验证 JWT 来保护该路由。
js
const jwtMiddleware = require('../middleware/jwtMiddleware'); // 自定义的 JWT 校验中间件
// 用户中心路由,保护路由,仅允许已认证用户访问
router.get('/user-center', jwtMiddleware, async (req, res) => {
try {
const user = await User.findById(req.user.id);
if (!user) return res.status(404).json({ message: 'User not found' });
res.status(200).json({
user: {
id: user.id,
username: user.username,
email: user.email,
createdAt: user.createdAt,
}
});
} catch (err) {
res.status(500).json({ message: 'Error retrieving user data', error: err });
}
});
4. JWT 验证中间件
我们需要创建一个中间件来验证 JWT,以便保护需要用户登录的路由。
js
const jwt = require('jsonwebtoken');
const jwtMiddleware = (req, res, next) => {
const token = req.headers['authorization'];
if (!token) return res.status(403).json({ message: 'No token provided' });
jwt.verify(token, 'secretKey', (err, decoded) => {
if (err) return res.status(401).json({ message: 'Invalid or expired token' });
req.user = decoded; // 将解码后的用户信息添加到请求中
next();
});
};
module.exports = jwtMiddleware;
5. 用户信息更新
用户可以更新自己的个人信息,例如修改邮箱或密码。我们将提供一个 PUT 路由来处理更新请求。
js
router.put('/user-center', jwtMiddleware, async (req, res) => {
const { email, password } = req.body;
const { id } = req.user;
try {
const user = await User.findById(id);
if (!user) return res.status(404).json({ message: 'User not found' });
if (email) user.email = email;
if (password) user.password = await bcrypt.hash(password, 10); // 加密新密码
await user.save();
res.status(200).json({ message: 'User information updated' });
} catch (err) {
res.status(500).json({ message: 'Error updating user data', error: err });
}
});
6. 总结
通过本章节的实现,您已经掌握了如何在 Express 中构建一个基本的登录和用户中心系统。您学会了如何:
- 使用 Passport.js 进行身份验证,处理用户的登录请求。
- 使用 JWT 来管理用户的会话,并实现对用户中心等敏感路由的保护。
- 创建用户注册和登录功能,处理用户信息的更新。
您可以根据需要扩展更多的功能,如密码重置、用户角色管理等,来进一步完善该系统。