node.js之express的token验证

本文详细介绍如何使用jsonwebtoken生成和验证token,包括在Express框架中设置中间件进行token验证,解析用户信息,以及处理token过期情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、用jsonwebtoken生成token
2、用express-jwt验证token是否过期或失效
3、用jsonwebtoken解析出token中的用户信息,比如用户id

注意:
使用res.json()发送响应时,需要 return res.json(),类似res.send()等函数也要加return,而且是所有的地方都要加,即使是a请求的响应没加return,当b请求到来时,也会报错:cant’t set headers after they are sent。

报错原因: 默认多次操作res或req

1、新建token_vertify.js文件,用于封装token生成和解析函数

如下:token_vertify.js

var jwt = require('jsonwebtoken');
var signkey = 'mes_qdhd_mobile_xhykjyxgs';

// 签发token
exports.setToken = function(username,userid){
	return new Promise((resolve,reject)=>{
		const token = jwt.sign({
			name:username,
			_id:userid
		},signkey,{ expiresIn:'0.01h' });
		resolve(token);
	})
}

// 验证token
exports.verToken = function(token){
	return new Promise((resolve,reject)=>{
		var info = jwt.verify(token.split(' ')[1],signkey);
		resolve(info);
	})
}

2、在 app.js 中验证token是否过期,如果没过期,则解析出用户信息

app.js中部分代码

var vertoken = require('./token_vertify.js');
var expressJwt = require('express-jwt');

// 解析token获取用户信息,并将用户信息存入 user 中以备使用
app.use(function(req, res, next) {
	var token = req.headers['authorization'];
	if(!token){
		return next();
	} else {
		vertoken.verToken(token).then((data)=> {
			req.user = data;
			return next();
		}).catch((error)=>{
			return next();
		})
	}
});

//验证token是否过期并约定哪些路由不用验证
app.use(expressJwt({
	secret: 'mes_qdhd_mobile_xhykjyxgs'
}).unless({
	path: ['/login']//除了这个地址,其他的URL都需要验证
}));

app.use('/login', loginRouter);
app.use('/users', usersRouter);

//当token失效返回提示信息
app.use(function(err, req, res, next) {
	if (err.status == 401) {
		return res.status(401).send('token失效');
	}
});

// 配置哪些路由需要 jwt 验证哪些不需要,也可以通过在路由中间件第二个参数配置,示例如下:
const expressJwt = require(‘express-jwt’);
const authenticate = expressJwt ({ secret: ‘mes_qdhd_mobile_xhykjyxgs’ });
app.use(‘/auth’, authenticate, loginRouter); // 需要token验证的接口
app.use(‘/notAuth’, usersRouter); // 不需要token验证的接口

3、在路由中使用前面定义的方法

login.js文件

var express = require('express');
var router = express.Router();
var settoken = require('./token_vertify.js');

// 生成token

router.post('/', function(req, res, next) {
	var username = 'slj';
	var userid = "111";
	settoken.setToken(username,userid).then((data)=>{
		return res.json({ token: data });
	})
	return next();
});

module.exports = router;

users.js文件

var express = require('express');
var router = express.Router();

// 身份验证
router.post('/vertify', function(req, res, next) {
	console.log(req.user)
	if(req.user){
		return res.json({
			msg:'身份验证成功'
		})
	}else{
		return res.json({
			msg:'未获取到用户信息'
		})
	}
	next();
});

module.exports = router;

看一下结果:

请求/login生成token并返回给客户端
在这里插入图片描述
成功验证token
在这里插入图片描述
当token失效
在这里插入图片描述
提供打包好的源码下载

### 如何在 Node.js 中使用 JWT 实现 Token 登录验证 以下是基于 `jsonwebtoken` 和其他必要依赖项的完整示例,展示如何在 Node.js 中实现基于 JWT 的用户登录和身份验证。 #### 安装必要的依赖包 为了实现此功能,需要安装以下模块: - **express**: 构建服务器端 API。 - **jsonwebtoken**: 生成和解析 JSON Web Tokens (JWT)。 - **bcryptjs**: 加密用户密码以便存储和比较。 运行以下命令以安装这些依赖项: ```bash npm install express jsonwebtoken bcryptjs body-parser ``` --- #### 创建项目结构并初始化服务 创建一个简单的 Express 应用来处理用户的注册、登录以及受保护路由的身份验证。 ##### 初始化文件 (`app.js`) ```javascript const express = require('express'); const bodyParser = require('body-parser'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); // 配置中间件 const app = express(); app.use(bodyParser.json()); // 假设这是数据库中的用户数据(实际开发中应连接真实数据库) let users = []; // 密钥用于签名 JWT const SECRET_KEY = 'your_secret_key_here'; // 注册新用户 app.post('/register', async (req, res) => { try { const { username, password } = req.body; // 检查用户名是否存在 if (users.find(user => user.username === username)) { return res.status(409).send({ message: 'Username already exists!' }); } // 对密码进行哈希加密 const hashedPassword = await bcrypt.hash(password, 8); // 存储用户信息 const newUser = { username, password: hashedPassword }; users.push(newUser); res.send({ message: 'User registered successfully!', user: newUser }); } catch (error) { res.status(500).send({ message: error.message || 'Some error occurred while registering.' }); } }); // 用户登录 app.post('/login', async (req, res) => { try { const { username, password } = req.body; const user = users.find(u => u.username === username); if (!user) { return res.status(404).send({ message: 'User not found!' }); } // 验证密码是否匹配 const isMatched = await bcrypt.compare(password, user.password); if (!isMatched) { return res.status(401).send({ accessToken: null, message: 'Invalid Password!' }); } // 如果成功,则签发 JWT const token = jwt.sign({ id: user.id, username: user.username }, SECRET_KEY, { expiresIn: '1h' }); res.send({ message: 'Login successful!', accessToken: token, }); } catch (error) { res.status(500).send({ message: error.message || 'Some error occurred while logging in.' }); } }); // 受保护的路由 function authenticateToken(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; if (!token) { return res.sendStatus(401); } jwt.verify(token, SECRET_KEY, (err, decoded) => { if (err) { return res.sendStatus(403); } req.user = decoded; // 将解码后的用户信息附加到请求对象上 next(); // 继续执行后续逻辑 }); } app.get('/protected-route', authenticateToken, (req, res) => { res.send(`Welcome ${req.user.username}! This route is protected.`); }); // 启动服务器 const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`)); ``` --- #### 示例解释 上述代码实现了以下几个核心功能: 1. **用户注册** 使用 `bcrypt` 来加密用户输入的密码,并将其保存在一个模拟数组中。如果用户名已存在,则返回错误消息[^3]。 2. **用户登录** 当用户提供有效的用户名和密码时,程序会通过 `bcrypt.compare()` 方法验证密码是否正确。如果验证成功,则生成一个带有过期时间的 JWT 并返回给客户端[^1]。 3. **受保护路由访问控制** 利用自定义中间件函数 `authenticateToken`,拦截对 `/protected-route` 路由的请求,检查是否有合法的 JWT 提供授权。如果没有提供有效令牌或者令牌无效,则拒绝访问[^2]。 --- #### 测试流程 1. 发送 POST 请求至 `/register` 接口完成用户注册操作。 2. 使用相同的账户发送 POST 请求至 `/login` 获取 JWT 访问令牌。 3. 在获取到的有效期内尝试 GET 请求访问 `/protected-route`,需携带 Authorization Header 设置为 Bearer `<access_token>` 形式。 ---
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值