当前位置: 首页 > news >正文

Node.js博客项目开发思路笔记

博客项目介绍

1. 目标

  • 开发一个博客系统,具备博客基本功能
  • 只开发 server 端,不关心前端

2. 需求

  • 首页、作者页、博客详情页
  • 登陆页
  • 管理中心、新建页、编辑页

3. 技术方案

数据如何存储

  • 博客
idtitlecontentcreatetimeauthor
1标题 1内容 11111112zhangsan
2标题 2内容 21111111lisi
  • 用户
idusernamepasswordrealname
1zhangsan123张三
2lisi.123李四

如何与前端对接接口,即接口设计

描述接口方法url参数备注
获取博客列表/api/blog/listgetauthor 作者,keyword搜索关键字参数为空,则不进行查询过滤
获取一篇博客的详情/api/blog/detailgetid
新增一篇博客/api/blog/newpostpost中有新增的信息
更新一遍博客/api/blog/updatepostidpostData中包含更新内容
删除一篇博客/api/blog/delpostid
登陆/api/user/loginpostpostData包含用户名和密码

4. 开发接口(原生node,不使用框架)

4.1 http请求过程

  1. DNS解析,建立TCP连接(三握四挥),发起请求;
  2. serve 端接收请求处理数据,响应返回数据;
  3. 客户端接收到数据,渲染页面,执行脚本。

4.2 搭建开发环境

  1. 使用 nodemon 检测文件变化,自动重启node项目;
  2. 使用 cross-env 设置环境变量。

4.3 路由和数据

  1. 初始化路由:根据之前的技术方案的设计,做出路由;
  2. 返回假数据:将路由和数据分离,符和设计原则。

4.4 项目结构

根目录下

  • bin/www.js 处理端口和 有关 http 服务的相关事宜
  • app.js 处理基本逻辑(导入路由函数,传递req,res参数),和 404 页面
  • router 文件夹,完成路由规则(分为 blog.js、 user.js ),只处理路由不关心数据的处理
  • controller/blog.js 文件, 连接数据库,处理数据,在 router/blog.js 中使用,类似工具
  • model/resModel 文件, 完成响应数据模块 resModel,封装成功和失败类,在 router/blog.js 的某个路径成功获取数据后就使用成功类响应数据和消息提示。

4.5 处理 post

使用 promise 优化 post 请求的数据,放入 req.body 里。对于请求方法不正确或者请求头不匹配直接 resolve 一个空对象,并不需要当作一个错误。应为读取 data 的过程是异步的,所以需要将原来的命中路由的逻辑放在promise中,在 app.js 中实现。

部分代码如下:

/*** 处理 post data*/
const getPostData = (req) => {const promise = new Promise((resolve, reject) => {// 方法不是 post...// 请求头格式不是 json...let postData = "";req.on("data", (chunk) => {// 将json格式的参数转为字符串保存postData += chunk.toString();});req.on("end", () => {// nullif (!postData) {resolve({});return;}// successresolve(JSON.parse(postData));});});return promise;
};
// 处理 post datagetPostData(req).then((postData) => {// 将数据放入bodyreq.body = postData;/***  blog 路由*/const blogData = handleBlogRouter(req, res);// 命中 blog 路由.../***  user 路由*/const userData = handleUserRouter(req, res);// 命中 user 路由...    // 处理 404...});

5.数据存储

5.1.实现思路

  • 建立数据库myblog,建立博客表、和用户表
  • conf/db.js 下封装数据库工具,处理开发和生产环境下的数据库连接配置
  • db/mysql.js使用promise获取数据库的数据,resolvegetList工具,在getList中只需处理 sql语句,然后在app.js 中使用.then,发送 res.end 给客户端

6.登陆功能

核心:登陆鉴权和信息存储

  • cookie和session

  • session 写入 redis

  • 开发登陆功能-和前端联调 Nginx 反向代理

session/cookie

前端保存 cookie 携带 userId,后端通过是否有 userId 进行一系列操作,当登陆成功但是没有 session 时需要设置 session

目前有关session的问题

  • session 是直接储存 js 变量,放在 node.js 进程内存中;
  • 第一,进程内存有限,访问量过大时内存爆增,可能导致服务崩溃;
  • 第二,正式线上运行时多进程,进程之间无法共享内存。

解决:使用 redis

为什么:

  • session 访问非常频繁,不能使用 mysql,对性能要求高。
  • 并且 session 可以丢失,无须内存永久保存。
  • session数据量不大,没必要使用 mysql

要使用 Redis,在 Node.js 中存储会话(session),你需要执行以下步骤:

1. 下载和安装 Redis:

官方网站(https://redis.io/download)

启动服务:执行 redis-server,建立连接和操作:执行:redis-cli

基本使用语法

  • 添加:set [key] [value]
  • 获取:get [key]
  • 删除:del [key]
  • 获取所有key: keys *

2. 配置 Redis:

安装完成后,你需要配置 Redis 服务器。打开 Redis 配置文件(redis.conf)并进行必要的更改。确保 bind 配置项设置为允许远程连接(如果需要从 Node.js 应用程序访问 Redis)。

3. 在 Node.js 中安装 Redis 客户端:

npm install redis

这将安装 Redis 客户端库,使你能够在 Node.js 应用程序中与 Redis 进行交互。

4. 在 Node.js 应用程序中存储会话:

首先,你需要在 Node.js 应用程序中创建与 Redis 的连接。使用 Redis 客户端库提供的方法进行连接。

const redis = require('redis');
const client = redis.createClient(); // 创建与 Redis 的连接client.on('error', (err) => {console.error('Redis连接错误:', err);
});// 储存会话示例
app.post('/login', (req, res) => {// 处理用户登录逻辑// ...// 在 Redis 中存储会话client.set(req.sessionID, JSON.stringify(req.user), (err, reply) => {if (err) {console.error('存储会话错误:', err);return res.status(500).send('存储会话失败');}console.log('会话已存储:', reply);res.send('登录成功');});
});

在上面的示例中,我们使用 Redis 客户端的 set 方法将会话数据以 JSON 字符串的形式存储在 Redis 中。req.sessionID 是会话的唯一标识符,通常存储在用户的浏览器 cookie 中。req.user 是用户对象,我们将其转换为 JSON 字符串后存储在 Redis 中。

和前端联调

  • 登陆依赖 cookie 必须使用 浏览器联调
  • cookie 跨域不共享,前端和 server 端必须同域
  • 需要使用 nginx 代理,使前后端同域

登陆总结:

Cookie和Session都是用于跟踪用户状态的技术。它们之间有一些区别:

  1. Cookie:Cookie是一种存储在客户端的小型文本文件,用于保存用户的一些信息。当用户访问一个网站时,服务器会将Cookie发送到用户的浏

  2. 用户在登录页面输入用户名和密码。

  3. 客户端将用户名和密码发送到服务器。

  4. 服务器验证用户名和密码。如果验证成功,服务器会创建一个Session,并将Session ID发送给客户端(通常通过Cookie)。

  5. 客户端保存Session ID,并在后续请求中将其发送回服务器。

  6. 服务器根据Session ID识别用户,并获取其会话信息。

在使用Redis存储Session信息时,可以将Session ID作为键,将用户会话信息作为值。这样,当服务器需要获取用户会话信息时,可以直接从Redis中查询,而不需要访问数据库,从而提高性能。同时,由于Redis支持分布式存储,可以方便地扩展Session存储容量。

7.日志

  1. 访问日志 access log (最重要);
  2. 自定义日志,包括自定义事件、错误记录。

大致思路:

  • 封装 utils log.js 工具
  • 使用 writerStream 分别实现 access 访问日志,和错误、事件日志
  • 分别导出使用
/*** 写日志的一小步操作* @param {Function} writeStream* @param {string} log*/
const writeLog = function (writeStream, log) {writeStream.write(log + "\n");
};/*** 写入流函数* @param {string} fileName -logs 文件夹下的文件名,你将要写入的文件* @return writeStream*/
const createWriteStream = function (fileName) {const fullFilePath = path.join(__dirname, "../", "../", "logs", fileName);const writeStream = fs.createWriteStream(fullFilePath, { flags: "a" });return writeStream;
};// 1. 写入访问日志
// 利用 createWriteStream 函数创建 access 写入流
const accessWriteStream = createWriteStream("access.log");
const access = function (log) {writeLog(accessWriteStream, log);
};// 2. 写入错误日志
...
// 3. 写入事件日志
...
module.exports = {...
};

日志拆分

使用 linux 的 crontab 命令,即定时任务。

使用 crontab -e 写入在什么时候执行什么文件

* 0 * * * sh /Users/jiangchuanyou/Desktop/项目/node博客项目/src/utils/copy.sh

以上就是在每天凌晨0点执行以下脚本

#!/bin/sh
cd /Users/jiangchuanyou/Desktop/项目/node博客项目/logs
cp access.log $(date +%Y-%m-%d).access.log
echo '' > access.log

8. 安全

  • sql 注入:窃取数据库内容;

解决方案:mysql 自带 escape 函数

  • xss 攻击:窃取前端 cookie 内容;

解决方案:转换特殊字符,使用 xss 函数,下载 npm 包 xss -s,直接使用 xss 函数包裹变量,以免生成危险的 js 代码

前端预防 xss 攻击

  1. 输入验证和过滤:对于用户输入的数据,进行输入验证和过滤,确保只接受预期的数据类型和格式。可以使用正则表达式、白名单过滤或使用专门的输入验证库来检查和清理用户输入。

  2. HTML转义:将用户输入的数据进行适当的 HTML 转义,确保任何特殊字符都被转义为它们的等效实体表示形式。这样可以防止恶意脚本在页面中执行。可以使用专门的转义函数或库,如htmlspecialchars等。

  3. 跨站点脚本保护:禁止内联 JavaScript 代码、限制只接受特定的 HTML 标签和属性。使用安全的 HTML 渲染库或模板引擎,这些库会自动转义用户输入。

  4. HTTP-only Cookie:将敏感信息存储在 HTTP-only Cookie 中,确保 JavaScript 无法访问该信息。这样可以减少 XSS 攻击者窃取会话信息的可能性。

  5. 内容安全策略(Content Security Policy,CSP):使用 CSP 可以限制页面中可以执行的脚本和资源。通过配置 CSP,可以指定允许的域、资源类型和加载方式,以减少 XSS 攻击的风险。

  6. 防止拼接 HTML 字符串:避免直接拼接用户输入的数据来构建 HTML 字符串。而是使用 DOM 操作或模板引擎来动态生成 HTML,确保数据被正确地转义和处理。

  7. 安全编码实践:遵循安全的编码实践,避免在代码中出现漏洞,如不信任的数据源、不安全的 eval() 使用、动态执行用户输入的代码等。

  • 密码加密:保障用户信息安全

9. 总结

流程图

相关文章:

Node.js博客项目开发思路笔记

博客项目介绍 1. 目标 开发一个博客系统,具备博客基本功能只开发 server 端,不关心前端 2. 需求 首页、作者页、博客详情页登陆页管理中心、新建页、编辑页 3. 技术方案 数据如何存储 博客 idtitlecontentcreatetimeauthor1标题 1内容 11111112z…...

python 之 shutil 文件的复制、删除、移动文件以及目录,并支持文件的归档、压缩和解压

一、shutil shutil 模块于文件和文件集合的高级操作,包括:复制、删除、移动文件以及目录,并支持文件的归档、压缩和解压等 二、使用例子 复制文件及权限 shutil.copy(src, dst)复制文件及权限;src 和 dst 文件路径。dst 文件名或…...

jface

JFace 是建立在 SWT 之上的 UI 部件,它是 SWT 的扩展并能和SWT交互。 ApplicationWindow和Action org.eclipse.jface.window.ApplicationWindow; JFace为了简化窗口的设计特别设计了类,比如ApplicationWindow这一个类,它里面包含了六个默认…...

六级备考28天|CET-6|听力第一讲|基本做题步骤与方法|13:30~14:30

目录 1. 重点词汇 proofread / ˈpruːfriːd / v.校对,校阅 autonomous adj.独立的 obsession n. 喜好 ample …...

系统设计 - 设计一个速率限制器

实施速率限制器的位置主要取决于我们的应用程序、技术栈、技术团队等因素。通常有三个位置可供选择:客户端、服务器端或中间件。 客户端是不可靠的地方来执行速率限制,因为恶意行为者可以轻易伪造客户端请求。 比将速率限制器放在服务器端更好的方法是使…...

[技术分享]Android平台实时音视频录像模块设计之道

实现背景 录像有什么难的?无非就是数据过来,编码保存mp4而已,这可能是好多开发者在做录像模块的时候的思考输出。是的,确实不难,但是做好,或者和其他模块有非常好的逻辑配合,确实不容易。 好多…...

JDKMissionControl官方用户指南--人工翻译

1. JMC8新增功能 暂时用不到,暂略 2. JDK Mission Control是什么 JMC是一组高级工具,用于管理、监视、分析Java应用程序并排除其故障。JMC能够对代码性能、内存和延迟等领域进行高效而详细的数据分析,而不会引入通常与分析和监控工具相关的…...

MySql-高级(分库分表问题简析) 学习笔记

文章目录 1. 为什么要分库分表?2. 用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?3. 你们具体是如何对数据库如何进行垂直拆分或水平拆分的?4. 分库分表时,数据迁移方案5. 如何设计可以动态扩容缩容…...

【5.20】五、安全测试——安全测试工具

目录 5.4 常见的安全测试工具 1. Web漏洞扫描工具——AppScan 2. 端口扫描工具——Nmap 3. 抓包工具——Fiddler 4. Web渗透测试工具——Metasploit 小提示:Kali Linux 5.4 常见的安全测试工具 安全测试是一个非常复杂的过程,测试所使用到的工具也…...

【13900k】i9 核显升级驱动

这里写自定义目录标题 官方的助手不能用显卡控制中心提示最新的更新搜索显卡 intel uhd graphics 770 手动下载安装自定义音频为啥也要卸载?新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片…...

使用Python将绿色转换为红色、红色转换为蓝色的图像处理

使用Python将绿色转换为红色、红色转换为蓝色的图像处理 在图像处理中,我们经常需要对图像进行颜色转换和修改。本篇博客介绍了如何使用Python的Pillow库来读取一个文件夹中的所有图像,并将其中的绿色转换为红色,红色转换为蓝色。我们还展示…...

Web2与Web3开发的不同之处

Web2是引入交互功能的第二代互联网,也是我们今天所熟悉的。随着Web的不断发展,第三代互联网,也被称为Web3,正处于积极开发中。Web3引入了在区块链上运行的去中心化和无需许可的系统。但是Web2和Web3开发之间有什么区别呢&#xff…...

递增数组的判断【python实现】

有时候需要对某一组数组的数据进行判断是否 递增 的场景,比如我在开发一些体育动作场景下,某些肢体动作是需要持续朝着垂直方向向上变化,那么z轴的值是会累增的。同理,逆向考虑,递减就是它的对立面。 下面是查找总结到…...

在自定义数据上训练 YOLOv8 实例分割

图像分割是一个核心视觉问题,可以为大量用例提供解决方案。从医学成像到分析流量,它具有巨大的潜力。实例分割,即对象检测+分割,甚至更强大,因为它允许我们在单个管道中检测和分割对象。为此,Ultralytics YOLOv8 模型提供了一个简单的管道。在本文中,我们将对自定义数据…...

洛谷密钥被破解:加密安全面临新挑战

密钥管理是加密系统中非常重要的一环,它涉及到密钥的生成、存储、分发、管理和销毁等多个方面。在密码学中,密钥是保护数据隐私和安全性的核心因素之一,因此,确保密钥的安全和保密性显得尤为重要。在2016年举办的 CQOI 数论竞赛中…...

02 Android开机启动之BootLoader及kernel的启动

Android开机启动之BootLoader及kernel的启动 1、booloader的启动流程 第一阶段:硬件初始化,SVC模式,关闭中断,关闭看门狗,初始化栈,进入C代码 第二阶段:cpu/board/中断初始化;初始化内存以及flash,将kernel从flash中拷贝到内存中,执行bootm,启动内核 2、kernel的启…...

代码随想录算法训练营 Day 49 | 121.买卖股票的最佳时机,122.买卖股票的最佳时机 II

121.买卖股票的最佳时机 讲解链接:代码随想录-121.买卖股票的最佳时机 确定 dp 数组以及下标的含义: dp[i][0] 表示第 i 天持有股票所得最多现金dp[i][1] 表示第 i 天不持有股票所得最多现金 确定递推公式: 如果第 i 天持有股票即 dp[i][0]&…...

精炼计算机网络——数据链路层(一)

文章目录 前言3.1 数据链路和帧3.1.1 数据链路和帧3.1.2 三个基本问题 3.2 点对点协议PPP3.2.1 PPP协议的特点3.2.2 PPP协议3.2.3 PPP协议的工作状态 总结 前言 上篇文章,我们一同学完了物理层的全部内容,在本篇文章中,我们初步学习数据链路…...

猿创征文|Spring系列框架之面向切面编程AOP

⭐️前面的话⭐️ 本篇文章将介绍一种特别重要的思想,AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。 …...

IoT架构设计

当前有一个支持5000万用户并发访问的网站,每个用户都有一个IOT设备,用户可以查看设备状态,接受设备通知 1.架构设计 针对不同的业务量模型,可以采用不同的架构设计,如下: 低业务量模型 针对低业务量模型…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

对象回调初步研究

_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...

当下AI智能硬件方案浅谈

背景: 现在大模型出来以后,打破了常规的机械式的对话,人机对话变得更聪明一点。 对话用到的技术主要是实时音视频,简称为RTC。下游硬件厂商一般都不会去自己开发音视频技术,开发自己的大模型。商用方案多见为字节、百…...