个人blog-1: 拾忆生活
个人blog-2: 极简-拾忆生活
欢迎大家来踩,同步更新
e x p o r t s 是 m o d u l e . e x p o r t s 的 别 名 ( 地 址 引 用 关 系 ) ; 导 出 对 象 最 终 以 m o d u l e . e x p o r t s 为 准 \color{red}exports是module.exports的别名(地址引用关系) ;导出对象最终以module.exports为准 exports是module.exports的别名(地址引用关系);导出对象最终以module.exports为准
a.js
// 在模块内部定义变量
let version = 1.0;
// 在模块内部定义方法(say是方法)
const sayHi = name => `您好, ${
name}`;
// 向模块外部导出数据
exports.version = version;
exports.sayHi = sayHi;
module.exports.version = version;
module.exports.sayHi = sayHi;
b.js
// 导入模块a
let a = require('./b');
// 输出b模块中的version变量
console.log(a.version);
// 调用b模块中的sayHi方法 并输出其返回值
console.log(a.sayHi('我'));
可省略global
global.console.log('我是global对象下面的console.log方法输出的内容');
global.setTimeout(function (){
console.log('123');
}, 2000)
等价:
setTimeout(function (){
console.log('123');
}, 2000)
npm i fs
fs.reaFile('文件路径/文件名称','文件编码', callback);
fs.writeFile('文件路径/文件名称', '数据', callback);
fs.readFile('./demo.txt', 'utf8', (err, doc) => {
// 如果文件读取出错err 是一个对象 包含错误信息
// 如果文件读取正确 err是 null
// doc 是文件读取的结果
console.log(err);
console.log(doc);
});
fs.writeFile('./demo.txt', '即将要写入的内容', err => {
if (err != null) {
console.log(err);
return;
}
console.log('文件内容写入成功');
})
npm i path
路径拼接语法,自动结尾加’’
path.join(‘路径1’, ‘路径2’, …)
const path = require('path');
const finalPath = path.join('public', 'uploads','avatar');
console.log(finalPath);
输出:
public\uploads\avatar
1.项目上线,HTML、CSS、JS文件压缩合并
2.语法转换(es6、less …)
3.公共文件抽离
4.修改文件浏览器自动刷新
npm i gulp -g
npm i gulp-cli -g
s r c 目 录 放 置 源 代 码 文 件 \color{red}src目录放置源代码文件 src目录放置源代码文件
s r c d i s t 目 录 放 置 构 建 后 文 件 \color{red}srcdist目录放置构建后文件 srcdist目录放置构建后文件
gulpfile.js
const gulp = require('gulp');
// 使用gulp.task()方法建立任务
gulp.task('first', () => {
// 获取要处理的文件,pipe中将处理后的文件输出到dist目录
gulp.src('./src/css/base.css').pipe(gulp.dest('./dist/css'));
});
执行上面的文件gulpfile.js:
在命令行中输入gulp task的第一个参数
gulp first
安装
npm i gulp-htmlmin
npm i gulp-file-include
···
// 引用gulp模块
const gulp = require('gulp');
const htmlmin = require('gulp-htmlmin');
const fileinclude = require('gulp-file-include');
const less = require('gulp-less');
const csso = require('gulp-csso');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
// 使用gulp.task建立任务
// 1.任务的名称
// 2.任务的回调函数
gulp.task('first', () => {
console.log('我们人生中的第一个gulp任务执行了');
// 1.使用gulp.src获取要处理的文件,使用gulp.dest输出处理的文件
gulp.src('./src/css/base.css')
.pipe(gulp.dest('dist/css'));
});
// html任务
// 1.html文件中代码的压缩操作 2.抽取html文件中的公共代码
gulp.task('htmlmin', () => {
gulp.src('./src/*.html')
.pipe(fileinclude())
// 压缩html文件中的代码,选择压缩空格
.pipe(htmlmin({
collapseWhitespace: true }))
.pipe(gulp.dest('dist'));
});
// css任务
// 1.less语法转换 2.css代码压缩
gulp.task('cssmin', () => {
// 选择css目录下的所有less文件以及css文件
gulp.src(['./src/css/*.less', './src/css/*.css'])
// 将less语法转换为css语法
.pipe(less())
// 将css代码进行压缩
.pipe(csso())
// 将处理的结果进行输出
.pipe(gulp.dest('dist/css'))
});
// js任务
// 1.es6代码转换 2.代码压缩
gulp.task('jsmin', () => {
gulp.src('./src/js/*.js')
.pipe(babel({
// 它可以判断当前代码的运行环境 将代码转换为当前运行环境所支持的代码
presets: ['@babel/env']
}))
.pipe(uglify())
.pipe(gulp.dest('dist/js'))
});
// 复制文件夹
gulp.task('copy', () => {
gulp.src('./src/images/*')
.pipe(gulp.dest('dist/images'));
gulp.src('./src/lib/*')
.pipe(gulp.dest('dist/lib'))
});
// 构建任务
gulp.task('default', ['htmlmin', 'cssmin', 'jsmin', 'copy']);
执行上面的文件gulpfile.js:
在命令行中输入gulp task的第一个参数
gulp htmlmin
gulp gulp-file-include
npm下载地址切换工具:
//安装模块
npm i nrm -g
//选择下载地址
nrm ls
//切换下载地址
nrm use taobao
//再次查看下载地址
nrm ls
退出即可
再npm i xxx可更快的下载其他包
1.在"scripts"中,添加别名操作
"build":"nodemon app.js"
npm run build
代替nodemon app.js操作命令2.在"scripts"中
"name": "node-1"
"main": "index.js"
Node.js会假设它是系统模块去node_modules文件夹中
首先看是否有该名字的JS文件
再看是否有该名字的文件夹(node-1)
如果是文件夹看里面是否有(index.js)
如果没有index.js查看该文件夹中的package.json中的main选项确定模块入口文件,否则找不到报错
express是对http的封装,express 会在后台调用http模块
app.listen() == http.Server.listen()
http模块
const http = require('http');
const app = http.createServer();
app.listen(3000);
express模块
const express = require('express');
const app = express();
app.listen(3000);
注意:https模块
const https = require('https');
const app = https.createServer();
app.listen(3000);
发送到浏览器页面,不是控制台
HTTP状态码、内容类型
//写头部的信息(设置http状态码和内容类型;编码信息)
res.writeHead(200, {
'content-type': 'text/html;charset=utf8'
});
用到npm i url(url模块)
url.parse(req.url, true) 要解析的url地址,将查询参数解析成对象形式
let { query, pathname } = url.parse(req.url, true);
注: g e t 请 求 参 数 在 地 址 栏 中 \color{red}get请求参数在地址栏中 get请求参数在地址栏中
if (pathname == '/index' || pathname == '/') {
res.end('欢迎来到首页
');
}else if (pathname == '/list') {
res.end('welcome to listpage');
}else {
res.end('not found');
}
整体:
第一个参数是请求名称
app.on('request', (req, res) => {
// console.log(req.method);
// console.log(req.url);
// console.log(req.headers['accept']);
res.writeHead(200, {
'content-type': 'text/html;charset=utf8'
});
console.log(req.url);
let {
query, pathname } = url.parse(req.url, true);
console.log(query.name)
console.log(query.age)
if (pathname == '/index' || pathname == '/') {
res.end('欢迎来到首页
');
}else if (pathname == '/list') {
res.end('welcome to listpage');
}else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post')
} else if (req.method == 'GET') {
res.end('get')
}
});
路由概念:客户端请求地址与服务器端程序代码的对应关系。简单的说,就是请求什么响应什么。
目的:得到请求路径,去除请求参数
const pathname = url.parse(req.url).pathname;
// 获取请求方式
const method = req.method.toLowerCase();
// 获取请求地址
const pathname = url.parse(req.url).pathname;
if (pathname == '/index' || pathname == '/') {
res.end('欢迎来到首页
');
}else if (pathname == '/list') {
res.end('welcome to listpage');
}else {
res.end('not found');
}
if (req.method == 'POST') {
res.end('post')
} else if (req.method == 'GET') {
res.end('get')
}
});
if (method == 'POST') {
res.end('post')
} else if (method == 'GET') {
res.end('get')
}
再引入:
const app = http.createServer();
app.on('request', (req, res) => {
// 获取用户的请求路径
let pathname = url.parse(req.url).pathname;
//判断,如果路径==/,则默认的html路径,如果路径!=/,则就是pathname的路径
pathname = pathname == '/' ? '/default.html' : pathname;
// 将用户的请求路径转换为实际的服务器硬盘路径
let realPath = path.join(__dirname, 'public' + pathname);
let type = mime.getType(realPath)
// 读取文件(第一个参数路径)
fs.readFile(realPath, (error, result) => {
// 如果文件读取失败
if (error != null) {
//返回状态码和返回内容的字符编码
res.writeHead(404, {
'content-type': 'text/html;charset=utf8'
})
res.end('文件读取失败');
return;
}
res.writeHead(200, {
'content-type': type
})
res.end(result);
});
});
app.listen(3000);
console.log('服务器启动成功')
需要npm i querystring 模块
// 用于创建网站服务器的模块
const http = require('http');
// 处理post请求参数模块
const querystring = require('querystring');
app.on('request', (req, res) => {
//请求参数传递触发
//参数传递完成触发
//变量用于拼接
let postParams = '';
//params是传递过来的参数
req.on('data', params => {
postParams += params;
});
//querystring模块处理请求参数
req.on('end', () => {
console.log(querystring.parse(postParams));
});
res.end('ok');
});
静态资源:服务器端不需要处理,可以直接响应给客户端的资源
动态资源:相同的请求地址不同的响应资源
如
http://www.itcast.cn/article?id=1
http://www.itcast.cn/article?id=2
同步sync、异步async
在浏览器中全局对象是window,在Node中全局对象是global。
Node中全局对象下有以下方法,可以在任何地方使用,global可以省略。
console.log() 在控制台中输出
setTimeout() 设置超时定时器
clearTimeout() 清除超时定时器
setInterval() 设置间歇定时器
clearInterval() 清除间歇定时器
同步API可以从返回值中拿到API执行的结果;
但是异步API是不可以的(代码执行顺序不同)
console.log('before');
setTimeout(function (){
console.log('last');
}, 2000)
console.log('after');
输出:
before
after
last
console.log('代码开始执行')
setTimeout(function () {
console.log('2s')
}, 2000)
setTimeout(function () {
console.log('0s')
}, 0)
console.log('代码结束执行')
输出:
代码开始执行
代码结束执行
0s
2s
定义函数的参数:callback
相当于调用函数的参数:匿名函数function (data) {console.log(data);}
function getMsg (callback) {
setTimeout(function () {
callback({
msg: 'hello node.js'
})
}, 2000)
}
getMsg(function (data) {
console.log(data);
});
执 行 异 步 时 , 异 步 A P I 后 面 代 码 的 执 行 依 赖 当 前 异 步 A P I 的 执 行 结 果 , 但 要 执 行 后 续 代 码 在 执 行 的 时 候 异 步 A P I 还 没 有 返 回 结 果 \color{red}执行异步时,异步API后面代码的执行依赖当前异步API的执行结果,但要执行后续代码在执行的时候异步API还没有返回结果 执行异步时,异步API后面代码的执行依赖当前异步API的执行结果,但要执行后续代码在执行的时候异步API还没有返回结果
粗暴方法:
const fs = require('fs');
fs.readFile('./1.txt', 'utf8', (err, result1) => {
console.log(result1)
fs.readFile('./2.txt', 'utf8', (err, result2) => {
console.log(result2)
fs.readFile('./3.txt', 'utf8', (err, result3) => {
console.log(result3)
})
})
});
解 决 异 步 a p i 执 行 时 , 可 以 顺 序 执 行 异 步 代 码 后 面 的 代 码 \color{red}解决异步api执行时,可以顺序执行异步代码后面的代码 解决异步api执行时,可以顺序执行异步代码后面的代码
简单方法(不引入promise模块)
链 式 编 程 \color{red}链式编程 链式编程
function p1 () {
return new Promise ((resolve, reject) => {
fs.readFile('./1.txt', 'utf8', (err, result) => {
resolve(result)
})
});
}
function p2 () {
return new Promise ((resolve, reject) => {
fs.readFile('./2.txt', 'utf8', (err, result) => {
resolve(result)
})
});
}
function p3 () {
return new Promise ((resolve, reject) => {
fs.readFile('./3.txt', 'utf8', (err, result) => {
resolve(result)
})
});
}
p1().then((r1)=> {
console.log(r1);
return p2();
}).then((r2)=> {
console.log(r2);
return p3();
}).then((r3) => {
console.log(r3)
})
解决异步编程的回调地狱问题
const fs = require('fs');
let promise = new Promise((resolve, reject) => {
fs.readFile('./100.txt', 'utf8', (err, result) => {
if (err != null) {
reject(err);
}else {
resolve(result);
}
});
});
promise.then((result) => {
console.log(result);
})
.catch((err)=> {
console.log(err);
})
e s 7 异 步 的 a s y n c 、 a w a i t \color{red}es7异步的async、await es7异步的async、await
更简单方法1
async function p1 () {
throw '发送错误'
return 'p1';
}
async function p2 () {
throw '发送错误'
return 'p2';
}
async function p3 () {
throw '发送错误'
return 'p3';
}
async function run () {
let r1 = await p1()
let r2 = await p2()
let r3 = await p3()
console.log(r1)
console.log(r2)
console.log(r3)
}
run();
a s y n c 异 步 读 文 件 \color{red}async异步读文件 async异步读文件
更简单方法2
const fs = require('fs');
const promisify = require('util').promisify;
const readFile = promisify(fs.readFile);
async function run () {
let r1 = await readFile('./1.txt', 'utf8')
let r2 = await readFile('./2.txt', 'utf8')
let r3 = await readFile('./3.txt', 'utf8')
console.log(r1)
console.log(r2)
console.log(r3)
}
run();
npm i serve-favicon
var favicon = require('serve-favicon');
app.use(favicon(__dirname+'/public/images/favicon.ico'));
见MongoDB用户信息后台管理.md
npm i art-template
//拼接字符串模块
npm i path
path.join()
template
方法是用来拼接字符串的
index.art
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
head>
<body>
{
{ name }}
{
{ age }}
body>
html>
app.js
const views = path.join(__dirname, 'views', 'index.art');
// 将特定模板与特定数据进行拼接
const html = template(views, {
name: '张三',
age: 20,
content: '我是标题
'
})
标准语法: { { 数据 }}
原始语法:<%=数据 %>
注:
{ { content }}
content: '我是标题
'
不 会 解 析 h 1 标 签 \color{red}不会解析h1标签 不会解析h1标签{ {@ content }}
content: '我是标题
'
会 解 析 h 1 标 签 \color{red}会解析h1标签 会解析h1标签
<p>{
{ name }}p>
<p>{
{ 1 + 1 }}p>
<p>{
{ 1 + 1 == 2 ? '相等' : '不相等' }}p>
<p>{
{ content }}p>
<p>{
{@ content }}p>
<p><%= name %>p>
<p><%= 1 + 2%>p>
<p><%= 1 + 1 == 2 ? '相等' : '不相等' %>p>
<p><%= content%>p>
<p><%- content%>p>
//02.js
const html = template(views, {
name: '张三',
age: 17
})
//02.art
{
{
if age > 18}}
年龄大于18
{
{
else if age < 15 }}
年龄小于15
{
{
else}}
年龄不符合要求
{
{
/if}}
//03.js
const html = template(views, {
users: [{
name: '张三',
age: 20,
sex: '男'
},{
name: '李四',
age: 30,
sex: '男'
}]
});
//模板03.art
<ul>
{
{
each users}}
<li>
{
{
$value.name}}
{
{
$value.age}}
{
{
$value.sex}}
</li>
{
{
/each}}
</ul>
//04.js
const html = template(views, {
msg: '我是首页'
});
//子模板header.art
我是头部
//子模板footer.art
我是底部
//主模板04.art
{
{
include './common/header.art' }}
<div> {
{
msg }} </div>
{
{
include './common/footer.art' }}
父模板
block 'xx'
子模板
extend 'aa.art'
block 'xx'
//app.js
const html = template(views, {
msg: '首页模板'
});
//父模板layout.art
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
{
{block 'link'}} {
{/block}}
head>
<body>
{
{block 'content'}} {
{/block}}
body>
html>
//子模板05.art
{
{extend './common/layout.art'}}
{
{block 'link'}}
<link rel="stylesheet" type="text/css" href="./main.css">
{
{/block}}
{
{block 'content'}}
<p>{
{ msg }}p>
{
{/block}}
npm i art-template
npm i path
npm i dateformat
js文件
变量名即dateformat模块暴露的变量名
template.defaults.root = 模板目录
template.defaults.imports.变量名 = 变量值;
template.defaults.extname = '.art'
art模板文件
dateFormat(time, 'yyyy-mm-dd')
//06.js
const template = require('art-template');
const path = require('path');
const dateFormat = require('dateformat');
template.defaults.root = path.join(__dirname, 'views');
template.defaults.imports.dateFormat = dateFormat;
template.defaults.extname = '.html';
//写后缀
const html = template('06.art', {
time: new Date()
});
//06和.html进行拼接(只写文件名,不用写后缀,因为已经配置)
console.log(template('06', {
}));
console.log(html);
//06.art
{
{
dateFormat(time, 'yyyy-mm-dd')}}
//06.html
我是06.html模板
见art-template-学生信息管理.md
npm i express
npm i url
Express是一个基于Node平台的web应用开发框架
区别:
原生node
app.on('request', (req, res) => {
// 获取客户端的请求路径
// 获取GET参数
let {
pathname,query } = url.parse(req.url,true);
// 对请求路径进行判断 不同的路径地址响应不同的内容
if (pathname == '/' || pathname == 'index') {
res.end('欢迎来到首页');
} else if (pathname == '/list') {
res.end('欢迎来到列表页页');
} else {
res.end('抱歉, 您访问的页面出游了');
}
// 获取POST参数
let postData = '';
req.on('data', (chunk) => {
postData += chunk;
});
req.on('end', () => {
console.log(querystring.parse(postData)
}));
});
req.query(获取GET参数)
http://localhost:3000/?name=zhangsan$age=20
req.body(获取POST参数)
app.use(bodyParser.urlencoded({extended: false}))
注:拦截所有请求
express框架
// 引入body-parser模块
const bodyParser = require('body-parser');
// 配置body-parser模块
app.use(bodyParser.urlencoded({
extended: false }));
// 当客户端以get方式访问/时
app.get('/', (req, res) => {
res.send('Hello Express');
// 获取GET参数
console.log(req.query);
});
// 当客户端以post方式访问/add路由时
app.post('/add', (req, res) => {
res.send('使用post方式请求了/add路由');
// 获取POST参数
console.log(req.body);
});
post请求对应html
<form action="http://localhost:3000/add" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" name="">
form>
app.use
是express注册中间件的方法。
app.use(function(req, res) {
res.writeHead(200, {
"Content-Type": "text/plain" });
res.end("Hello world!\n");
});
中间件作用:
例子(直接app.use拦截请求)
//网站公告
app.use((req, res, next) => {
res.send('当前网站正在维护...')
})
//自定义404页面
app.use((req, res, next) => {
// 为客户端响应404状态码以及提示信息
res.status(404).send('当前访问的页面是不存在的')
})
//路由保护1
app.use('/admin', (req, res, next) => {
// 用户没有登录
let isLogin = true;
// 如果用户登录
if (isLogin) {
// 让请求继续向下执行
next()
}else {
// 如果用户没有登录 直接对客户端做出响应
res.send('您还没有登录 不能访问/admin这个页面')
}
})
//路由保护2
app.get('/admin', (req, res) => {
res.send('您已经登录 可以访问当前页面')
})
中间件 参 数 是 函 数 \color{red}参数是函数 参数是函数:
const app = express();
//调用函数,实参是对象形式,用到其属性
app.use(fn ({
a: 2}))
//obj是函数形参,obj.a调用其属性
function fn (obj) {
return function (req, res, next) {
if (obj.a == 1) {
console.log(req.url)
}else {
console.log(req.method)
}
next()
}
}
app.get('/', (req, res) => {
// 接收post请求参数
res.send('ok')
})
app.use((req, res, next) => { xxx; next(); });
app.get('请求路径', '处理函数')
app.post('请求路径', '处理函数')
// 引入body-parser模块
const bodyParser = require('body-parser');
// 配置body-parser模块
app.use(bodyParser.urlencoded({ extended: false }));
app.get('/request', (req, res, next) => {
req.name = "张三";
next();
});
app.get('/request', (req, res) => {
res.send(req.name);
});
路由:请求路径参数+请求参数(:xxx)冒号是占位符
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.get('/index/:id/:name/:age', (req, res) => {
// 接收post请求参数
res.send(req.params)
})
try {
await User.find({
name: '张三'})
}catch(ex) {
next(ex);
}
//app.use集中处理
app.use((err, req, res, next) => {
res.status(500).send('服务器发生未知错误'+err.message);
})
//单个处理
app.get('/index', (req, res, next) => {
fs.readFile('./01.js', 'utf8', (err, result) => {
if (err != null) {
next(err)
}else {
res.send(result)
}
})
//捕获错误(异步实现)
app.get("/", async (req, res, next) => {
try {
await User.find({
name: '张三'})
}catch(ex) {
next(ex);
}
});
一个请求地址下,继续接第二个请求地址
/home
/home/index
const express = require('express')
// 创建路由对象
const home = express.Router();
// 将路由和请求路径进行匹配
app.use('/home', home);
// 在home路由下继续创建路由
home.get('/index', () => {
// /home/index
res.send('欢迎来到博客展示页面');
});
访问地址:localhost:3000/find/123
app.get('/find/:id', (req, res) => {
console.log(req.params); // {id: 123}
});
/home
/home/index
/admin
/admin/index
// home.js
const home = express.Router();
home.get('/index', () => {
res.send('欢迎来到博客展示页面');
});
module.exports = home;
// admin.js
const admin = express.Router();
admin.get('/index', () => {
res.send('欢迎来到博客管理页面');
});
module.exports = admin;
// app.js
const home = require('./route/home.js');
const admin = require('./route/admin.js');
app.use('/home', home);
app.use('/admin', admin);
1.重要
app.use(express.static('public'));
app.use(express.static('images'));
http://localhost:3000/favicon.ico
2. 访 问 文 件 存 放 在 一 个 不 存 在 的 目 录 下 面 \color{red}访问文件存放在一个不存在的目录下面 访问文件存放在一个不存在的目录下面(如virtual),可以指定挂载路径方式实现(第一个参数)
app.use('/virtual', express.static('public'));
如找到:http://localhost:3000/virtual/images/favicon.ico
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
3.构造函数
express.Router
是一个构造函数,调用后返回一个路由器实例
var router = express.Router();
router.get(
)等定义的访问路径,挂载到根目录
app.use('/', router);
npm i art-template
npm i express-art-template
app.engine('art', require('express-art-template'));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'art');
res.render('index' ,{msg: 'message'});
res.render(
)函数作用:
app.js
app.engine('art', require('express-art-template'));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'art');
app.get('/index', (req, res) => {
res.render('index', {
msg: 'message'
})
});
index.art
{
{
msg}}
在页面中看到message
将变量设置到app.locals对象下面,这个数据在所有的模板中都可以获取到。
app.locals.users =[...];
app.locals.users = [{
name: '张三',
age: 20
},{
name: '李四',
age: 20
}]
//第一个模板
app.get('/index', (req, res) => {
res.render('index', {
msg: '首页'
})
});
//第二个模板
app.get('/list', (req, res) => {
res.render('list', {
msg: '列表页'
});
})
list.art
{
{
msg}}
<ul>
{
{
each users}}
<li>
{
{
$value.name}}
{
{
$value.age}}
</li>
{
{
/each}}
</ul>
哈希单程加密方式(在加密的密码中再加入随机字符串)
bcrypt依赖环境第一种
npm install -g node-gyp
npm install --global --production windows-build-tools
bcryptjs依赖环境第二种
npm install bcryptjs
genSalt();
方法生成随机字符串
hash('123456', salt);
方法加密
compare(xxx, xxx);
方法比对
使用方法一
//导入bcrypt模块
const bcrypt = require('bcryptjs');
//生成随机字符串,genSalt()方法生成随机字符串盐
//默认随机程度为10
let salt = await bcrypt.genSalt(10);
//使用随机字符串对密码进行加密
let pass = await bcrypt.hash('123456',salt);
//比对密码
let isValid = await bcrypt.compare('123456', pass);
使用方法二
var bcrypt = require('bcryptjs');
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash("明文密码", salt, function(err, hash) {
// Store hash in your password DB.
});
});
cookie是存储在客户端中,供 服 务 器 端 \color{red}服务器端 服务器端存储数据
在网站中 F12
找到
Application
在 Storge
下的 Cookies
Network
在当前主网站名中点击,找到 Request Headers
下的 Cookie
(字符串形式)session是对象,存储在服务器端的内存中
sessionId
做唯一标识过程
第一次访问
1.客户端将请求数据(用户名、密码)传递给服务器端
2.服务器端接收到请求参数,并验证请求参数成功后
3.服务器端使用 session,为该用户生成唯一的 sessionId ,在session对象中存储用户信息
4.服务器端将sessionId写入客户端的cookie,发送给客户端
以后访问
5.客户端下次访问浏览器时,cookie会自动发送给服务器端
6.服务器端拿到cookie中存储的sessionId,然后在服务器端存储的session对象中验证当前的sessionId
7.验证成功后,服务器端响应数据
app.use()
处理先拦截请求,再交给session处理
//导入express-session模块
const session = require('express-session');
//配置session1
app.use(session( {
secret:"secret key"} ));
// 配置session2
app.use(session({
secret: 'secret key',
saveUninitialized: false,
cookie: {
maxAge: 24 * 60 * 60 * 1000
},
resave: true,
}));
是js对象的规则描述语言和验证器
string()
alphanum()
email()
min(2).max(5)
required()
error(new Error('该属性没有通过验证'))
regex(/xxx/)
可以指定数组
xxx:[Joi.string(),Joi.number()]
Joi.validate(xx,xx)
Joi.validate({username:'abc',birthyear:1900},schema);
async function run () {
try {
// 实施验证
await Joi.validate({
username: 'ab', birth: 1800}, schema);
}catch (ex) {
console.log(ex.message);
return;
}
console.log('验证通过')
}
JOi.js 完整
// 引入joi模块
const Joi = require('joi');
// 定义对象的验证规则
const schema = {
username: Joi.string().alphanum().min(2).max(10).required().error(new Error('username属性没有通过验证')),
//该正则方法跟上面等价
password:Joi.string().regex(/^[a-zA-Z0-9]{2,10}$/),
birth: Joi.number().min(2).max(10).error(new Error('birth没有通过验证')),
email:Joi.string().email()
};
//验证规则
async function run () {
try {
// 实施验证
await Joi.validate({
username: 'ab', birth: 1800}, schema);
}catch (error) {
console.log('验证错误:'+error.message);
return;
}
console.log('验证通过')
}
//运行
run();
见node-博客.md