当前位置:网站首页>Node.js的基本使用(三)数据库与身份认证
Node.js的基本使用(三)数据库与身份认证
2022-08-03 23:53:00 【啾比特】
数据库
数据库基本概念
数据库是用来组织,存储和管理数据的仓库,用户可以对数据库中的数据进行增删改查等操作。
常见的数据库及分类
- MySQL数据库:目前使用最广泛,流行度最高
- Oracle数据库
- SQL Server数据库
- Mongodb数据库
MySQL,Oracle,SQL Server属于传统型数据库(关系型数据库),mongodb属于新型数据库(非关系型数据库或NoSQL数据库)
传统型数据库的数据组织结构
在传统型数据库中,数据的组织结构为数据库,数据表,数据行,字段这四个部分组成
在项目中操作数据库的步骤
- 安装操作MySQL数据库的第三方模块
- 通过mysql模块连接到MySQL数据库
- 通过mysql模块执行SQL语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unfCs7Qp-1659433888464)(https://raw.githubusercontent.com/Koiiiilin/MyImage/main/202207221159546.png)]
安装mysql模块
mysql模块是托管于npm上的第三方模块,执行npm install mysql
配置mysql模块
在使用mysql模块操作MySQL数据库之前,必须先对mysql模块进行必要的配置。
// 导入mysql模块
const mysql = require("mysql")
// 建立与mysql数据库的连接关系
const db = mysql.createPool({
host:'127.0.0.1',
user:'root',
password:'root',
database:'mydb'
})
测试一下,mysql是否连接成功,
db.query('select 1',(err,results)=>{
if(err){
return console.log(err.message);
}
console.log(results)
})
使用mysql模块操作MySQL数据库
1.查询数据
db.query('select * from sp_type',(err,results)=>{
if(err){
return console.log(err.message);
}
console.log(results)
})
执行select语句查询的结果是数组。
2.插入数据
// 插入数据
const obj = {
type_name:'饮水机',
delete_time:null
}
db.query("insert into sp_type (type_name) values (?,?)",[obj.type_name,obj.delete_time],(err,results)=>{
if(err) return console.log(err.message);
if(results.affectedRows === 1){
console.log("插入数据成功");
}
})
插入数据的便捷方式
向表中新增数据时,如果数据对象的每个属性和数据表的字段一一对应,则可以通过如下方式快速插入数据。
db.query("insert into sp_type set ?",obj,(err,res)=>{
if(err) return console.log(err.message);
console.log(res);
})
3.更新数据
var today = date.format(new Date(),'YYYY-MM-DD');
db.query("update sp_type set type_name=? ,delete_time = ? where type_id = 3",['电脑',today],(err,result)=>{
if(err) return console.log(err.message);
if(result.affectedRows === 1){
console.log("更新数据成功!");
}
})
更新数据的便捷方式
与插入数据类似,在更新表格数据时,如果数据对象的每个属性和数据表的字段一一对应,可以使用更加简便的方式
var type = {
type_name :'电脑',
delete_time:today,
type_id:9
}
db.query("update sp_type set ? where type_id = ?",[type,type.type_id],(err,result)=>{
if(err) return console.log(err.message);
if(result.affectedRows === 1){
console.log("更新数据成功!");
}
})
4、删除数据
注:如果SQL语句中有多个占位符,则必须使用数组为每个占位符指定具体的值,若只有一个则可以省略数组
db.query("delete from sp_type where type_id = ?", 8, (err, result) => {
if (err) return console.log(err.message);
if (result.affectedRows === 1) {
console.log("删除数据成功!");
}
})
标记删除
使用delete语句,会真实的把数据从表中删除,操作存在一定的风险。为了保险起见,推荐使用标记删除的行是,来模拟删除的动作。通过设置类似于isDelete的状态字段来标记当前数据是否被删除。当需要进行删除的时候,实际上执行的修改isDelete的update操作。
db.query("update sp_user set isDelete = ? where user_id = ?", [1,1], (err, result) => {
if (err) return console.log(err.message);
if (result.affectedRows === 1) {
console.log("删除数据成功!");
}
})
WEB开发模式
1、服务端渲染的Web开发模式
服务器发送给客户端的HTML页面,是在服务器通过字符串的拼接,动态生成的,因此,客户端不需要使用Ajax这样的技术额外请求页面的数据。
优点
- 前端耗时少,浏览器只需要渲染即可
- 有利于SEO,爬虫更容易获取信息
缺点
- 占用服务器端资源,如果请求较多,会对服务器造成一定的访问压力
- 不利于前后端分离,开发效率低,无法进行分工合作
2、前后端分离的web开发模式
前后端分离的概念:前后端分离的开发模式依赖于ajax,后端只负责提供API接口,前端使用Ajax调用接口的开发模式。
优点
- 开发体验好,前端专注于UI页面的开发,后端专注于api的开发,且前端有更多的选择性
- 用户体验好,可以轻松实现页面的局部刷新
- 减轻了服务器端的渲染压力,因为页面最终是在每个用户的浏览器中生成
缺点
- 不利于SEO,爬虫无法爬取页面的有效信息
身份认证
不同开发模式下的身份认证
对于服务器端渲染和前后端分离这两种开发模式来说,分别有着不同的身份认证方案:
- 服务端渲染推荐使用Session认证机制
- 前后端分离推荐使用JWT认证机制
Session认证机制
Http协议的无状态性
客户端每次HTTP请求都是独立的,连续多个请求之间没有直接关系,服务器不主动保留每次HTTP请求的状态。
什么是Cookie
Cookie是存储在用户浏览器中的一段不超过4KB的字符串,由一个名称,一个值和其他几个用于控制Cookie有效期、安全性、适用范围的可选属性组成。
不同域名下的Cookie各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie发送到服务器。
几大特性
- 自动发送
- 域名独立
- 过期时限
- 4KB限制
Cookie在身份认证中的作用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-phnLQIMM-1659433888468)(https://raw.githubusercontent.com/Koiiiilin/MyImage/main/202208021058834.png)]
Cookie不具有安全性
由于Cookie是存储在浏览器中的,而且浏览器也提供了读写Cookie的API,因此Cookie很容易被伪造,不具有安全性,因此不建议服务器将重要的隐私数据,通过Cookie 的形式发送给浏览器。
在Express中使用Session认证
- 安装express-session中间件
在Express项目中,只需要安装express-session中间件,即可在项目中使用Session认证
npm install express-session
- 配置express-session 中间件
express-session中间件安装成功后,需要通过app.use()来注册session中间件
var session = require('express-session')
append.use(session({
secret:'key',//任意字符
resave:false,//固定写法
saveUninitialized:true//固定写法
}))
- 向session中存数据
当express-session中间件配置成功后,即可通过req.session来访问和使用seesion对象
- 清空session
调用req.session.destroy()函数,即可清空服务器保存的session信息,只会清空当前用户对应的session
JWT认证机制
session认证的局限性
Session认证机制需要配合Cookie才能实现,由于Cookie默认不支持跨域访问,所以当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域Session认证。
JWT的组成部分
JWT通常由三部分组成,分别是Header,Payload,Signature三者之间使用英文‘.’分隔.
Header.Payload.Signature
- Payload部分才是真正的用户信息,是经过加密后生成的字符串
- Header和Signatures是安全性相关的部分,只是为了保证Token的安全
JWT的使用方法
客户端收到服务器返回的JWT后通常将它存储在localStorage或者sessionStorage中。推荐的做法是把JWT放在HTTP请求头的Authorization字段中,AUthorization:Bearer <token>
在Express中使用JWT
- 安装JWT相关的包
npm install jsonwebtoken express-jwt
- jsonwebtoken用于生成JWT字符串
- express-jwt用于将JWT 字符串解析还原成json对象
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
- 定义secret密钥
为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,需要专门定义一个用于加密和解密的secret密钥
- 当生成JWT字符串的时候,需要使用secret密钥对用户的信息进行加密,最终得到加密好的JWT字符串
- 当把JWT字符串解析还原成JSON对象时,需要使用secret密钥进行解密
// 定义secret密钥,本质就是一个字符串
const secretKey = 'abcdefg ^_^'
在登录成功后生成JWT字符串
调用jsonwebtoken包提供的sign()方法,将用户信息加密成JWT字符串,响应给客户端
// 在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
// 参数1:用户的信息对象
// 参数2:加密的秘钥
// 参数3:配置对象,可以配置当前 token 的有效期
// 记住:千万不要把密码加密到 token 字符中
const tokenStr = jwt.sign({
username: userinfo.username }, secretKey, {
expiresIn: '30s' })
将JWT字符串还原为JSON对象
客户端每次在访问那些有权限接口的时候,都需要主动通过请求头中的Authorization字段将Token字符串发送到服务器进行身份认证
app.use(expressJWT({
secret: secretKey }).unless({
path: [/^\/api\//] }))
//高版本算法发生改变
app.use(expressJWT({
secret:secretKey,algorithms:['HS256']}).unless({
path:[/^\/api\//]}))
nodejs中post请求方式,req.body接值为空如何解决
https://blog.csdn.net/ccf19881030/article/details/109121566
使用req.user获取用户信息
当express-jwt中间件配置成功之后,即可在有权限的接口中使用req.user()对象,来访问JWT字符串中解析出来的用户信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FBChy0J5-1659433888469)(https://raw.githubusercontent.com/Koiiiilin/MyImage/main/202208021749797.png)]
捕获解析JWT失败后产生的错误
当使用express-jwt解析Token字符串时,如果客户端发送过来的Token字符串过期或者不合法,会产生一个解析失败的错误,影响项目的正常运行.
app.use((err, req, res, next) => {
// 这次错误是由 token 解析失败导致的
if (err.name === 'UnauthorizedError') {
return res.send({
status: 401,
message: '无效的token',
})
}
res.send({
status: 500,
message: '未知的错误',
})
})
边栏推荐
猜你喜欢
Salesforce的中国区业务可能出现新变化,传言可能正在关闭
小身材有大作用——光模块寿命分析(二)
- the skip/skipif Pytest learning
A simple understanding of TCP, learn how to shake hands, wave hands and various states
设置工作模式与环境(下):探查和收集信息
用两个栈模拟队列
"Miscellaneous" barcode by Excel as a string
RSS订阅微信公众号初探-feed43
Justin Sun was invited to attend the 36氪 Yuan Universe Summit and delivered a keynote speech
孙宇晨受邀参加36氪元宇宙峰会并发表主题演讲
随机推荐
A simple understanding of TCP, learn how to shake hands, wave hands and various states
curl使用指南
1067 Sort with Swap(0, i)
小身材有大作用——光模块基础知识(一)
Why Flutter Flutter of tutorials is the best choice for business?
响应式织梦模板塑身瑜伽类网站
libnet
RSS feeds WeChat public - feed43 asain
设置工作模式与环境(下):探查和收集信息
初始 List 接口
(PC+WAP)织梦模板不锈钢类网站
密码学基础以及完整加密通讯过程解析
Creo 9.0二维草图的诊断:重叠几何
SolidEdge ST8安装教程
重新认识浏览器的渲染过程
sqlnet.ora文件与连接认证方式的小测试
FPGA按键消抖+蜂鸣器
Super perfect version of the layout have shortcut, background replacement (solve the problem of opencv Chinese path)
Flutter教程之为什么 Flutter 是创业的最佳选择?
孙宇晨:Web3.0和元宇宙将协助人类更加全面地进入网络世界