1. 密码加密 bcrypt
- 哈希加密是单程加密方式:1234 => abcd
- 在加密的密码中加入随机字符串可以增加密码被破解的难度。
- 安装 npm install bcrypt
- bcrypt依赖的其他环境
- python 2.x
- node-gyp
npm install -g node-gyp
- node-gyp
- windows-build-tools
npm install --global --production windows-build-tools
- windows-build-tools
// 导入bcrypt模块
const bcrypt = require('bcrypt');
// 生成随机字符串 gen => generate 生成 salt 盐
let salt = await bcrypt.genSalt(10);
// 使用随机字符串对密码进行加密
let pass = await bcrypt.hash('明文密码', salt);
2.cookie与session (express-session)
cookie:浏览器在电脑硬盘中开辟的一块空间,主要供服务器端存储数据。
- cookie中的数据是以域名的形式进行区分的。
- cookie中的数据是有过期时间的,超过时间数据会被浏览器自动删除。
- cookie中的数据会随着请求被自动发送到服务器端。
session:实际上就是一个对象,存储在服务器端的内存中,在session对象中也可以存储多条数据,每一条数据都有一个sessionid做为唯一标识。 - 在node.js中需要借助express-session实现session功能
- 安装 npm install express-session
const session = require('express-session');
app.use(session({ secret: 'secret key' }));
//登录成功在session中添加username
//将用户名存储在请求对象中
req.session.username = user.username;
//登录成功可以将user全局开放
req.app.locals.userInfo = user;
//根据session中的username判断登录拦截
(req.url != '/login' && !req.session.username)
3.Joi
- JavaScript对象的规则描述语言和验证器。
- 安装 npm install joi
const Joi = require('joi');
const schema = {
username: Joi.string().alphanum().min(3).max(30).required().error(new Error(‘错误信息’)),
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
access_token: [Joi.string(), Joi.number()],
birthyear: Joi.number().integer().min(1900).max(2013),
email: Joi.string().email()
};
Joi.validate({ username: 'abc', birthyear: 1994 }, schema);
示例 user.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
//引入joi模块
const Joi = require('joi');
//创建用户集合
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
minlength: 2,
maxlength: 20
},
email: {
type: String,
//保证邮箱地址在插入数据库时不重复
unique: [true, '邮箱已存在']
},
password: {
type: String,
required: true
},
// admin 超级管理员
// normal 普通用户
role: {
type: String,
required: true
},
// 0 启用状态
// 1 禁用状态
statue: {
type: Number,
default: 0
}
})
;
const User = mongoose.model('User', userSchema);
async function createUser() {
const salt = await bcrypt.genSalt(10);
const pass = await bcrypt.hash('123456', salt);
const user = await User.create({
username: 'ithedan',
password: pass,
email: '358603587@qq.com',
role: 'admin',
statue: 0
});
}
// createUser();
//用户验证信息
const validateUser = (obj) => {
//定义对象的验证规则
const schema = {
username: Joi.string().min(2).max(12).required().error(new Error('用户名不符合要求')),
email: Joi.string().email().required().error(new Error('邮箱格式不符合要求')),
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/).error(new Error('密码格式不符合要求')),
role: Joi.string().valid('normal', 'admin').required().error(new Error('角色值非法')),
statue: Joi.number().valid('0', '1').required().error(new Error('状态值非法'))
};
//实施验证
return Joi.validate(obj, schema);
};
//将用户模块作为模块导出
module.exports = {
User,
validateUser
};
验证
try {
await validateUser(req.body);
} catch (e) {
//验证没有通过
//JSON.stringfy()将对象类型转换成字符串数据类型
return next(JSON.stringify({path:'***',message:e.message}));
}
4 .formidable
- 作用:解析表单,支持get请求参数,post请求参数、文件上传
- 安装 npm install formidable
// 引入formidable模块
const formidable = require('formidable');
// 创建表单解析对象
const form = new formidable.IncomingForm();
// 设置文件上传路径
form.uploadDir = "/my/dir";
// 是否保留表单上传文件的扩展名
form.keepExtensions = false;
// 对表单进行解析
form.parse(req, (err, fields, files) => {
// fields 存储普通请求参数
// files 存储上传的文件信息
});
5 .数据分页 mongoose-sex-page
- 用来处理数据库分页查询的操作
- 安装 npm install mongoose-sex-page
const pagination = require('mongoose-sex-page');
pagination(集合构造函数).page(1) .size(20) .display(8) .exec();
//查询所有数据(关联查询populate)
//page指定当前页
//size 指定每页显示的数据条数
//display 指定客户端要显示的页面数量
//exec() 向数据库中发送查询请求
const articles = await pagination(Article).find({}).page(page).size(2).display(3).populate('author').exec();
//返回数据结构
{
"page": 1,
"size": 2,
"total": 31,
"records": [
{
"publishDate": "2020-04-01T00:00:00.000Z",
"cover": "\\uploads\\upload_58395dfb9a86c4247cb27aeca0429945.png",
"_id": "5ea55868e148fa1930a3f671",
"title": "测试441",
"author": {
"statue": 0,
"_id": "5ea00b63bdec8411ec0d6f5b",
"username": "ithedan",
"password": "$2b$10$dSo.A4giEZZmhp2vdflvWuIvQCKkjrF9w6VNQbE4SM2ihSC8Bglme",
"email": "358603587@qq.com",
"role": "admin",
"__v": 0
},
"content": "测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容",
"__v": 0
},
{
"publishDate": "2020-04-01T00:00:00.000Z",
"cover": "\\uploads\\upload_811382460ba9fab583151705c3044e99.png",
"_id": "5ea55898e148fa1930a3f673",
"title": "测试91",
"author": {
"statue": 0,
"_id": "5ea00b63bdec8411ec0d6f5b",
"username": "ithedan",
"password": "$2b$10$dSo.A4giEZZmhp2vdflvWuIvQCKkjrF9w6VNQbE4SM2ihSC8Bglme",
"email": "358603587@qq.com",
"role": "admin",
"__v": 0
},
"content": "测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容测试测试内容内容",
"__v": 0
}
],
"pages": 16,
"display": [
1,
2,
3
]
}
6 文件读取 FileReader(图片)
//当选择文件控件上传对象
var file = document.querySelector('#file');
//当用户选择完文件以后
file.onchange = function () {
//创建文件读取对象
var reader = new FileReader();
//用户选择的的文件列表
// console.log(this.files[0]);
//读取文件
reader.readAsDataURL(this.files[0]);
//监听onload事件
reader.onload = function () {
// console.log(reader.result);
$('#img-preview').attr('src', reader.result);
}
};