数据库是用来组织,存储和管理数据的仓库,用户可以对数据库中的数据进行增删改查等操作。
常见的数据库及分类
MySQL,Oracle,SQL Server属于传统型数据库(关系型数据库),mongodb属于新型数据库(非关系型数据库或NoSQL数据库)
传统型数据库的数据组织结构
在传统型数据库中,数据的组织结构为数据库,数据表,数据行,字段这四个部分组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unfCs7Qp-1659433888464)(https://raw.githubusercontent.com/Koiiiilin/MyImage/main/202207221159546.png)]
mysql模块是托管于npm上的第三方模块,执行npm install 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)
})

db.query('select * from sp_type',(err,results)=>{
if(err){
return console.log(err.message);
}
console.log(results)
})
执行select语句查询的结果是数组。

// 插入数据
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);
})
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("更新数据成功!");
}
})
注:如果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("删除数据成功!");
}
})
服务器发送给客户端的HTML页面,是在服务器通过字符串的拼接,动态生成的,因此,客户端不需要使用Ajax这样的技术额外请求页面的数据。
优点
缺点
前后端分离的概念:前后端分离的开发模式依赖于ajax,后端只负责提供API接口,前端使用Ajax调用接口的开发模式。
优点
缺点
对于服务器端渲染和前后端分离这两种开发模式来说,分别有着不同的身份认证方案:
客户端每次HTTP请求都是独立的,连续多个请求之间没有直接关系,服务器不主动保留每次HTTP请求的状态。
Cookie是存储在用户浏览器中的一段不超过4KB的字符串,由一个名称,一个值和其他几个用于控制Cookie有效期、安全性、适用范围的可选属性组成。
不同域名下的Cookie各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie发送到服务器。
几大特性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-phnLQIMM-1659433888468)(https://raw.githubusercontent.com/Koiiiilin/MyImage/main/202208021058834.png)]
由于Cookie是存储在浏览器中的,而且浏览器也提供了读写Cookie的API,因此Cookie很容易被伪造,不具有安全性,因此不建议服务器将重要的隐私数据,通过Cookie 的形式发送给浏览器。
在Express项目中,只需要安装express-session中间件,即可在项目中使用Session认证
npm install express-session
express-session中间件安装成功后,需要通过app.use()来注册session中间件
var session = require('express-session')
append.use(session({
secret:'key',//任意字符
resave:false,//固定写法
saveUninitialized:true//固定写法
}))
当express-session中间件配置成功后,即可通过req.session来访问和使用seesion对象
调用req.session.destroy()函数,即可清空服务器保存的session信息,只会清空当前用户对应的session
Session认证机制需要配合Cookie才能实现,由于Cookie默认不支持跨域访问,所以当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域Session认证。

JWT通常由三部分组成,分别是Header,Payload,Signature三者之间使用英文‘.’分隔.
Header.Payload.Signature

客户端收到服务器返回的JWT后通常将它存储在localStorage或者sessionStorage中。推荐的做法是把JWT放在HTTP请求头的Authorization字段中,AUthorization:Bearer
npm install jsonwebtoken express-jwt
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
为了保证JWT字符串的安全性,防止JWT字符串在网络传输过程中被别人破解,需要专门定义一个用于加密和解密的secret密钥
// 定义secret密钥,本质就是一个字符串
const secretKey = 'abcdefg ^_^'
调用jsonwebtoken包提供的sign()方法,将用户信息加密成JWT字符串,响应给客户端
// 在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
// 参数1:用户的信息对象
// 参数2:加密的秘钥
// 参数3:配置对象,可以配置当前 token 的有效期
// 记住:千万不要把密码加密到 token 字符中
const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
客户端每次在访问那些有权限接口的时候,都需要主动通过请求头中的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
当express-jwt中间件配置成功之后,即可在有权限的接口中使用req.user()对象,来访问JWT字符串中解析出来的用户信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FBChy0J5-1659433888469)(https://raw.githubusercontent.com/Koiiiilin/MyImage/main/202208021749797.png)]
当使用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: '未知的错误',
})
})