在现代 Web 应用中,用户认证和授权是非常重要的一环。JSON Web Token(JWT)是一种安全的认证和授权方式,它能够让你在客户端和服务器之间传递安全可靠的信息。本文将介绍如何在 Express.js 中使用 JWT 进行用户认证和授权。
JWT 简介
JWT 是一种基于 JSON 的开放标准(RFC 7519),它定义了一种紧凑且自包含的方式用于在各方之间安全地传输信息。它由三部分组成:头部、载荷和签名。
头部包含了加密算法和类型信息,例如:
{
"alg": "HS256",
"typ": "JWT"
}载荷包含了需要传递的信息,例如:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}签名用于验证消息的完整性和真实性,它需要使用头部指定的加密算法和密钥生成。例如:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
使用 JWT 进行用户认证和授权
在 Express.js 中使用 JWT 进行用户认证和授权,需要进行以下步骤:
- 安装相关依赖
npm install jsonwebtoken express-jwt
- 创建 JWT 密钥
const jwtSecret = 'your_jwt_secret';
- 创建用户认证中间件
// www.javascriptcn.com code example
const jwt = require('jsonwebtoken');
const expressJwt = require('express-jwt');
const authenticate = expressJwt({
secret: jwtSecret,
algorithms: ['HS256'],
getToken: function (req) {
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
return req.headers.authorization.split(' ')[1];
}
return null;
}
});
const generateToken = function (user) {
const payload = {
sub: user.id,
name: user.name,
iat: Date.now()
};
const options = {
expiresIn: '1h'
};
return jwt.sign(payload, jwtSecret, options);
};
module.exports = {
authenticate,
generateToken
};其中,authenticate 中间件用于验证 JWT,generateToken 函数用于生成 JWT。
- 创建路由
// www.javascriptcn.com code example
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const authController = require('../controllers/authController');
const authMiddleware = require('../middlewares/authMiddleware');
router.post('/users', userController.create);
router.get('/users', authMiddleware.authenticate, userController.getAll);
router.get('/users/:id', authMiddleware.authenticate, userController.getOne);
router.put('/users/:id', authMiddleware.authenticate, userController.update);
router.delete('/users/:id', authMiddleware.authenticate, userController.delete);
router.post('/auth/login', authController.login);
module.exports = router;其中,auth/login 路由用于用户登录,其他路由需要使用 authMiddleware.authenticate 中间件进行 JWT 验证。
- 创建控制器和中间件
// www.javascriptcn.com code example
const User = require('../models/User');
const bcrypt = require('bcrypt');
const create = async function (req, res) {
try {
const user = new User(req.body);
await user.save();
res.status(201).send(user);
} catch (err) {
res.status(400).send(err);
}
};
const getAll = async function (req, res) {
try {
const users = await User.find();
res.send(users);
} catch (err) {
res.status(500).send(err);
}
};
const getOne = async function (req, res) {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).send();
}
res.send(user);
} catch (err) {
res.status(500).send(err);
}
};
const update = async function (req, res) {
try {
const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true });
if (!user) {
return res.status(404).send();
}
res.send(user);
} catch (err) {
res.status(500).send(err);
}
};
const deleteOne = async function (req, res) {
try {
const user = await User.findByIdAndDelete(req.params.id);
if (!user) {
return res.status(404).send();
}
res.send(user);
} catch (err) {
res.status(500).send(err);
}
};
const login = async function (req, res) {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(401).send({ message: 'Invalid email or password' });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).send({ message: 'Invalid email or password' });
}
const token = authMiddleware.generateToken(user);
res.send({ token });
} catch (err) {
res.status(500).send(err);
}
};
module.exports = {
create,
getAll,
getOne,
update,
deleteOne,
login
};其中,create、getAll、getOne、update 和 deleteOne 控制器用于增删改查用户,login 控制器用于用户登录。
// www.javascriptcn.com code example
const jwt = require('jsonwebtoken');
const expressJwt = require('express-jwt');
const jwtSecret = 'your_jwt_secret';
const authenticate = expressJwt({
secret: jwtSecret,
algorithms: ['HS256'],
getToken: function (req) {
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
return req.headers.authorization.split(' ')[1];
}
return null;
}
});
const generateToken = function (user) {
const payload = {
sub: user.id,
name: user.name,
iat: Date.now()
};
const options = {
expiresIn: '1h'
};
return jwt.sign(payload, jwtSecret, options);
};
module.exports = {
authenticate,
generateToken
};其中,authenticate 中间件用于验证 JWT,generateToken 函数用于生成 JWT。
示例代码
完整的示例代码可以在 GitHub 上找到。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d41249a941bf71347b69b8