第七课:Nodejs开发用户认证与JWT实践

在现代Web开发中,用户认证是一个至关重要的环节。随着前后端分离架构的流行,传统的Session认证方式逐渐暴露出了一些局限性。而JWT(JSON Web Token)作为一种无状态的认证机制,凭借其简洁、安全和高效的特性,在现代Web应用中得到了广泛应用。本文将详细介绍SessionToken认证的对比、JWT的原理与生成/验证流程、使用bcrypt加密用户密码,并通过实战展示如何在Node.js中实现登录鉴权中间件。

1. Session与Token认证对比

1.1 Session认证

Session认证是一种传统的认证方式,其基本原理是在用户登录成功后,服务器会在内存中(或数据库、缓存中)存储一份用户的登录信息(Session),然后将Session ID通过Cookie返回给客户端。每次客户端请求时,都会携带这个Session ID,服务器通过Session ID查找对应的Session数据,从而验证用户身份。

优点

  • 简单易用,适合初学者。
  • 安全性相对较高,Session信息存储在服务器端,不易被窃取。

缺点

  • 服务器需要存储Session数据,占用服务器资源。
  • 在分布式系统中,需要共享Session数据,增加了系统复杂性。
  • Session依赖于Cookie,对于非浏览器客户端(如手机APP)不适用。
1.2 Token认证

Token认证是一种无状态的认证方式,其核心思想是在用户登录成功后,服务器生成一个Token(通常是JWT)并返回给客户端。客户端在每次请求时,都会携带这个Token,服务器通过解析和验证Token来验证用户身份。

优点

  • 无状态,服务器无需存储Token数据,减轻了服务器负担。
  • 适合分布式系统,无需共享状态。
  • 跨域支持好,Token可以通过HTTP头部发送。

缺点

  • Token需要存储在客户端,存在被窃取的风险。
  • 实现相对复杂,需要一定的技术知识。

2. JWT原理与生成/验证流程

2.1 JWT原理

JWT(JSON Web Token)是一种用于双方之间安全传输信息的简洁的、URL安全的令牌标准。JWT由三部分组成:Header(头部)、Payload(负载)和Signature(签名)。

  • Header:包含令牌的类型(如JWT)和签名算法(如HS256)。
  • Payload:包含需要传递的信息,如用户ID、用户名、角色等。注意,Payload部分的数据是未加密的,因此不适合存储敏感数据。
  • Signature:通过对Header和Payload进行Base64编码并使用密钥加密生成的字符串,用于验证令牌的完整性和真实性。
2.2 JWT生成/验证流程

生成JWT

创建Header:指定令牌类型和签名算法。

{
    "alg": "HS256",
    "typ": "JWT"
}

创建Payload:包含用户信息和过期时间等。

{
    "sub": "1234567890",
    "name": "John Doe",
    "exp": 1625347200
}
  • 编码Header和Payload:将Header和Payload进行Base64编码。
  • 生成Signature:使用密钥对编码后的Header和Payload进行签名。
  • 拼接JWT:将编码后的Header、Payload和Signature用“.”拼接成完整的JWT。

验证JWT

  • 解析JWT:将JWT用“.”分割成Header、Payload和Signature三部分。
  • 验证Signature:使用相同的密钥对编码后的Header和Payload进行签名,并与JWT中的Signature进行比较。
  • 检查Payload:验证Payload中的信息(如过期时间)是否有效。

3. 使用bcrypt加密用户密码

bcrypt是一种基于Blowfish算法的密码哈希函数,专为抵御暴力破解攻击设计。它使用随机生成的字符串和可调节的工作因子来确保密码的安全性。

安装bcrypt

首先,你需要在Node.js项目中安装bcrypt库:

npm install bcrypt

bcrypt加密密码

const bcrypt = require('bcrypt');
 
async function hashPassword(password) {
    // 生成随机数据串
    const salt = await bcrypt.genSalt(10);

    // 加密密码
    const hashedPassword = await bcrypt.hash(password, salt);
    return hashedPassword;
}
 
// 使用示例
hashPassword('my_password').then(hashedPassword => {
    console.log('Hashed Password:', hashedPassword);
});

验证密码

const bcrypt = require('bcrypt');
 
async function comparePasswords(inputPassword, hashedPassword) {
  const isMatch = await bcrypt.compare(inputPassword, hashedPassword);
  return isMatch;
}
 
// 使用示例
comparePasswords('my_password', hashedPassword).then(isMatch => {
  console.log('Password Match:', isMatch);
});

4. 实战:实现登录鉴权中间件

4.1 安装必要的依赖

首先,你需要在Node.js项目中安装express和jsonwebtoken库:

npm install express jsonwebtoken
4.2 配置JWT密钥

在项目的配置文件中(如config.js)设置JWT密钥:

module.exports = {
    jwtSecret: 'your_jwt_secret_key'
};
4.3 实现登录接口
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const config = require('./config');
 
const app = express();
// 模拟用户数据库
const users = [];
 
app.post('/login', async (req, res) => {
    const { username, password } = req.body;

    const user = users.find(u => u.username === username);
    if (!user) {
        return res.status(401).send('用户或则密码错误');
    }

    const isMatch = await bcrypt.compare(password, user.hashedPassword);
    if (!isMatch) {
        return res.status(401).send('用户或则密码错误');
    }

    const token = jwt.sign({ username: user.username }, config.jwtSecret, { expiresIn: '1h' });
    res.json({ token });
});
 
app.listen(3000, () => {
    console.log('Server is running on http://localhost:3000');
});
4.4 实现JWT鉴权中间件
const jwt = require('jsonwebtoken');
const config = require('./config');
 
function authenticateJWT(req, res, next) {
    const token = req.headers['authorization'] && req.headers['authorization'].split(' ')[1];

    if (!token) {
        return res.status(403).send('认证的token数据必须传递');
    }

    jwt.verify(token, config.jwtSecret, (err, decoded) => {
    if (err) {
        return res.status(401).send('token数据错误');
    }

    req.user = decoded;
        next();
    });
}
 
// 使用中间件
app.use('/protected', authenticateJWT, (req, res) => {
    res.send('调用此接口的都是需要认证的接口');
});
4.5 测试登录和鉴权

登录接口测试:

curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username":"testuser","password":"testpassword"}'

响应示例:

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiaWF0IjoxNjI1MzQ3MjAwLCJleHAiOjE2MjUzNTA4MDB9.8y3H_m16G010a-35fJ8K5I9wM80_y3r4b3_Qe4-z55A"
}

受保护接口测试:

curl -X GET http://localhost:3000/protected -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiaWF0IjoxNjI1MzQ3MjAwLCJleHAiOjE2MjUzNTA4MDB9.8y3H_m16G010a-35fJ8K5I9wM80_y3r4b3_Qe4-z55A"

响应示例:

This is a protected route

结语

通过本文,我们详细介绍了Session与Token认证的对比、JWT的原理与生成/验证流程、使用bcrypt加密用户密码,并通过实战展示了如何在Node.js中实现登录鉴权中间件。希望这些内容能够帮助你更好地理解和应用用户认证与JWT技术。

关注我!!🫵 持续为你带来Nodejs相关内容。

### 嘉莲VR心理一体机参数配置说明 嘉莲VR心理一体机作为一款专门针对心理健康教育设计的产品,在硬件和技术方面进行了精心优化,旨在通过虚拟现实技术为用户提供沉浸式的心理辅导体验。 #### 硬件规格 - **处理器**:采用高性能四核ARM Cortex-A72 CPU,主频达到2.0GHz,能够流畅运行复杂的VR应用程序[^1]。 - **内存**:配备4GB LPDDR4X RAM,确保系统稳定性和多任务处理能力。 - **存储空间**:内置64GB eMMC闪存,支持扩展至最高512GB microSD卡,满足大量数据存储需求。 - **显示屏**:搭载高分辨率AMOLED屏幕,分辨率为3840×2160像素(4K),刷新率高达90Hz,带来清晰细腻的画面显示效果。 - **传感器**:集成九轴陀螺仪、加速度计和磁力计等多种传感组件,精准捕捉头部动作变化;同时具备眼动追踪功能,增强交互真实感。 - **音频系统**:双扬声器立体声音效配合主动降噪耳机接口,营造身临其境的声音环境。 - **电池续航**:内置大容量锂电池,典型使用场景下可连续工作约4小时以上。 #### 软件特性 - **操作系统**:基于Android定制开发的心理健康专用OS,界面简洁友好,易于操作。 - **应用生态**:预装丰富的心理学评估工具、放松训练程序以及冥想引导视频等内容资源库,覆盖多种常见心理问题解决方案。 - **云端服务**:连接专业的心理咨询师团队所提供的在线服务平台,实现远程指导反馈机制,帮助使用者获得更个性化的治疗建议。 ```json { "processor": "四核 ARM Cortex-A72, 主频 2.0 GHz", "memory": "4 GB LPDDR4X RAM", "storage": "64 GB eMMC (最大支持512 GB microSD)", "display": { "resolution": "3840x2160 (4K), 刷新率 90 Hz" }, "sensors": [ "九轴陀螺仪", "加速度计", "磁力计", "眼动追踪" ], "audio_system": "双扬声器 + 主动降噪耳机接口", "battery_life": "> 4 hours typical usage" } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值