node.js

node.js

node.js是一个基于v8引擎的javascript运行环境

底层是c/c++ 相当于把js代码通过node解析成c/c++从而进行底层的操作 js代码被翻译成c了

优点:

在这里插入图片描述

缺点:

在这里插入图片描述

运行node

node node_fun.js

// //如何在一个函数体里输出函数本身?
// function demo() {
//     console.log(arguments.callee);
// }
// demo()
console.log(arguments.callee.toString());


// function (exports, require, module, __filename, __dirname) {
// exports 用于支持comminjs模块化规范暴露语法
// require 用于支持commonjs 模块化规范引入语法
// module  用于支持commonjs模块化规范暴露语法
//  __filename   运行的文件路径名字 C:\Users\000\Desktop\0418\node\初识node\node_fun.js
// __dirname    运行文件路径 C:\Users\000\Desktop\0418\node\初识node

// }
//外层函数
//用于支持模块化语法
// 隐藏服务器内部实现
console.log(__filename);
console.log(__dirname);

global

node js组成部分

没有了BOM 服务器不需要

没有了DOM 没有浏览器窗口

没有了window 取而代之的叫做global全局变量

事件循环机制

/*

node事件循环模型

timers(定时器阶段–setTimeout,setinterval)

1.开始计时

2.执行定时器的回调

pending callbacks(系统阶段)

idle prepare(准备阶段)

poll(轮询阶段!!)

–如果回调队列有带执行的回调函数,从回调队列中取出回调函数,同步执行(一个一个执行)直到回调队列为空

–如果回调队列为空,等待回调函数被插入回调队列

–如果设置过setImmediate 进入下一个check阶段(为了执行setImmediate所设置的回调)

–如果未设置过setImmediate 等待回调函数被插入回调队列 若定时器到点了进入下一个check阶段

check(专门用于执行setImmediate所设置的回调)

close callbacks(关闭定时器回调阶段)

*/

// process.nextTick 人民币玩家,能在任意阶段优先执行,除了主线程

setTimeout(() => {

  console.log('timeout');

})

setImmediate(() => {

  console.log('我是setImmediate');

})
process.nextTick(() => {

  console.log('processnextTick');

})
console.log('我是主线程');

NPM

npm==软件管家

如何让一个普通文件夹变成一个包

npm init

命名要求:不能有中文,大写字母,不要与仓库包同名

  • 搜索 npm search jquery

  • 安装 npm i xxx

  • 安装生产依赖 npm i xxx -D

  • 全局安装 npm i xxx -g 全局安装的包指令到处可用 查看位置 npm root -g

  • 指定版本 npm i jquery@2

在这里插入图片描述

在这里插入图片描述

yarn命令

 npm i yarn -g
 yarn global dir
C:\Users\000\AppData\Local\Yarn\Data\global
C:\Users\000\AppData\Local\Yarn\bin
在环境变量添加上两条路径

在这里插入图片描述

在这里插入图片描述

buffer缓冲器

buffer是一个数组类似的对象,不同是buffer是专门用来保存二进制数据的

特点:

大小固定:在创建时就确定了,且无法调整

性能较好:直接对计算机的内存进行操作

每个元素大小为1字节

buffer时node中非常核心的模块,无序下载,无序引入,直接调用即可

// Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from()

// let num = new Buffer(123) //性能差在堆内存里开辟了一个空间 清理
// let num = new Buffer.alloc(123)  //性能比new buffer强  在堆内存里开辟了一个空间(空间没有人用过)
// console.log(num);
// let num = new Buffer.allocUnsafe(10)  //性能最好的一个
// console.log(num);
let num = new Buffer.from('xcl') //将一个数据存入一个buffer实例
console.log(num);
console.log(num.toString());


//buffer输出的时16进制,但是存储的是二进制
//buffer不为空  在堆内存开辟空间 可能残留别人用过的数据

fs模块

文件写入

/*node中的文件系统  写入文件
node 中有一个文件系统,就是对计算机中文件进行增删改查
node中,给我们提供了一个模块,叫做fs模块(文件系统),专门用于操作文件 直接引入

异步文件写入(简单文件写入)
    fs.writeFile(file,data[,options],callback){
        file  要写入的路径加文件名字
        data  要写入的数据
        options 可选参数(配置对象)
            encoding:设置文件编码编码方式:默认值utf8
            mode:默认值是0o666  设置文件操作权限
                -0o111  文件可被执行的权限
                -0o222  文件可被写入的权限
                -0o444  文件可被读取的权限
            flag  打开文件要执行的操作,默认值是w
                    -a 追加
                    -w 写入
                    callback 回调函数
            --err错误对象
    }
 //在node中原则:错误优先   
*/
const fs = require('fs')
//调用witeFile方法

fs.writeFile('./demo1.txt', '今天天气真晴朗222', { mode: 0o666, flag: 'a' }, (err) => {
    if (err) {
        console.log('写入失败');
    } else {
        console.log('成功');
    }
})
/**
    创建一个可写流
    
    fs.createWriteStream(path,[,options]){
         --path:要写入的文件路径+文件名+文件后缀
         --options配置对象(可选参数)
            flags: 
            encoding:
            fd: 文件统一标识符 Linux下的文件标识符
            mode:
            autoClose  自动关闭 文件  默认值:true
            emitClose  关闭 文件  默认值:false
            start 
    }

 */

const fs = require('fs')
//创建可写流
let ws = fs.createWriteStream('./demo2.txt')

//只要用到了流,就必须监测流的状态
ws.on('open', () => {
    console.log('打开了');
})
ws.on('close', () => {
    console.log('关闭了');
})

ws.write('美女')
ws.write('美女123')
ws.close()  //如果在node 8版本使用,数据会丢失
ws.end()  //在node 8 要用end关闭

文件读取

第一种

/*文件读取
    fs.readFile(path,[.options],callback)
        -path 要读取文件的路径+文件名+后缀
        - options 配置对象
        --callback 回调
        简单文件写入和读取都是一次性把所有要读取写入的内容加到内存中,容易造成内存泄漏
*/

let fs = require('fs')
fs.readFile('./demo2.txt', (err, data) => {
    if (err) {
        console.log(err);
    } else {
        console.log(data); //读取出来的文件是buffer16进制 用户存储的不一定是纯文本文本用toString()
        fs.writeFile('../hah', data, (err) => {
            if (err) console.log(err);
            else console.log('成功');
        })
    }
})


第二种

/**
 fs.createReadStream(path,[.options])
        path  要读取文件路径+文件名+后缀
        options 配置对象
            flags
            encoding
            mode
            autoClose
            emitClose
            start 开始位置
            end  结束位置 
            higWaterMark  每次读取数据的大小默认值是64*1024
 */

let fs = require('fs')

let rs = fs.createReadStream('./demo2.txt')
let ws = fs.createWriteStream('./123.txt')

rs.on('open', () => {
    console.log('打开了');
})
rs.on('close', () => {
    console.log('关闭了');
    ws.close()
})

ws.on('open', () => {
    console.log('打开了');
})
ws.on('close', () => {
    console.log('关闭了');
})

//给的可读流绑定一个data事件就会触发可读流自动读取内容
let result = rs.on('data', (data) => {
    //buffer实例的length属性,表示buffer实例占用内存空间大小
    console.log(data.length);//输出的是65536每次读取64kb内容
    ws.write(data)
    // ws.close() 若在此处关闭写入流,只会写入一次后续数据丢失
})
    // ws.close() 若在此处关闭写入流无法生成数据因为这是主线代码


数据库

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

配置window系统服务

让体验更好

https://www.cnblogs.com/ckfuture/p/14341752.html

https://www.yht7.com/news/123510

sc.exe create MongoDB binPath="\"C:\Program Files\MongoDB\Server\3.2\bin\mongod.exe\"  --service  --config=\"C:\Program Files\MongoDB\Server\3.2\mongod.cfg\"" DisplayName="MongoDB"  start="auto"

mongdb基本命令

db: 查看当前操作哪一个数据库
show dbs 查看数据库表
use text 切换到text数据库 如果不存在则创建
db.students.insert() 向当前数据库的students集合中插入一个文档
show collections 展示当前数据库中所有的集合

数据库crud

create

db.集合名.insert()

db.集合名.insertOne()

db.集合名.insertMany([文档对象])

//新增
db.students.insert({name:'zhangsan',age:18,sex:'男',grade:'高三',stu_id:'001'});
db.students.insertOne({name:'li',age:17,sex:'男',grade:'高1',stu_id:'002'});
db.students.insertMany([
{name:'xxx',age:17,sex:'男',grade:'高2',stu_id:'003'},
{name:'hh',age:17,sex:'男',grade:'高6',stu_id:'004'},
{name:'xcl',age:12,sex:'男',grade:'高1',stu_id:'005'}
])
read

db.集合名.find(查询条件,[,过滤])

​ db.students.find({age:18}) 查找年龄18所有信息

​ db.students.find({age:18,name:‘jack’}) 查找年龄18名字jack

常用操作符

小于  $lt
小于等于  $lte
大于  $gt
大于等于  $gte
不等于  $ne

逻辑或  $in $or
逻辑非  $nin
db.集合名.find({age:{$gte:20}})   查找年龄大于等于20

db.students.find({age:{$in:[18,20]}});  查找年龄是18或者20的人
db.students.find({$or:[{age:18},{age:20}]});

db.students.find({age:{$nin:[18]}});   查找年龄不是18所有人的信息
正则匹配
db.students.find({name:/^x/})   //查询首字母为X的

db.students.findOne({age:18})  找到一条数据就不往下找了
update

db.集合名.update(查询条件,要更新内容,[,配置对象])

db.students.update({name:'xcl'},{age:19})  将更新内容替换掉整个文档对象
db.students.update({name:'xcl'},{$set:{age:101}}) 使用$set 修改指定的内容,其他数据不变,不过只能匹配一个xcl  下面如果还有则忽略

db.students.update({name:'xcl'},{$set:{age:101}},{multi:true})

补充:
db.集合名.updateOne(查询条件,要更新内容,[,配置对象])
db.集合名.updateMany(查询条件,要更新内容,[,配置对象])
delete

db.集合名.remove(查询条件)

删除所有年龄小于等于19的学生
db.students.remove({age:{$lte:19}})

mongoos

借助第三方包连接数据库 mongoose 一个知名的用于帮助开发者连接mongoDB的包

在node平台下更简单,方便安全稳定操作mongoDB

在这里插入图片描述

连接数据库
//引入数据库
const mongoose = require("mongoose");
mongoose.set('useCreateIndex', true) //使用新索引配置器
// 连接数据库
mongoose.connect("mongodb://127.0.0.1:27017/test", {
    useNewUrlParser: true, //使用一个新的url解析器,解决安全问题
    useUnifiedTopology: true //使用统一新的拓扑图结构
});

//绑定数据库连接的监听

mongoose.connection.on('open', (err) => {
    if (err) {
        console.log(err);
    } else {
        console.log('成功');
    }
})

操作数据库
 //操作数据库
        //把数据库想象成我家的别墅
        // 1.有一个帮你看门的人--请来一个保安  引入模式对象
        let Schema = mongoose.Schema
        // 2.对进入的数据进行校验--制定进入你家的规则  创建约束对象
        let stuRule = new Schema({
            stu_id: {
                type: String,  //限制学号必须字符串
                required: true, //必填项
                unique: true //唯一的
            },
            name: {
                type: String,  //限制学号必须字符串
                required: true, //必填项

            },
            age: {
                type: Number,  //限制学号必须字符串
                required: true, //必填项

            },
            sex: {
                type: String,  //限制学号必须字符串
                required: true, //必填项

            },
            hobby: [String],//限制爱好只能为数组数组每一项必须字符串
            info: [Schema.Types.Mixed],  //接收所有类型
            date: {
                type: Date,
                default: Date.now()

            },
            enable_flag: {
                type: String,
                default: 'Y'
            }
        })
模型对象

告诉保安你的规则 创建模型对象

  let stu_mode = mongoose.model('students', stuRule)//用于生成某个集合所对应的模型对象
数据库新增操作
   stu_mode.create({
            stu_id: '007',
            name: '虎哥1',
            age: 18,
            sex: '女',
            hobby: ['xcl', 'cnm','hh'],
            info: 66,
        }, function (err, data) {
            if (err) {
                console.log(err + '失败');

            } else {
                console.log(data._doc);
            }
        })
查询操作
   stu_mode.find({ name: 'wlw' }, function (err, data) {
            if (err) {
                console.log(err);
            }
            else {
                console.log(data);
            }
        }).lean()

find方法:若有结果返回是一个对象

没结果返回一个null

模型对象.find(查询条件,[,投影]) 不管有没有数据返回一个数组

模型对象.findOne(查询条件,[,投影]) 找到返回一个对象,没有null

更新

模型对象.updateOne(查询条件,要更新的内容,[,配置对象])更新一个

模型对象.updateMany(查询条件,要更新的内容,[,配置对象]) 更新多个

    stu_mode.update({ name: 'wlw' }, { age: 16 }, function (err, data) {
            if (err) {
                console.log(err);
            } else {
                console.log(data);
            }
        })
        stu_mode.updateOne({ name: 'wlw' }, { age: 111 }).then(res => console.log(res))
模块化编码
1.连接数据库db
const mongoose = require('mongoose');
mongoose.set('useCreateIndex', true);
// 连接数据库
module.exports = new Promise((resolve, reject) => {
    //2.连接数据库
    mongoose.connect("mongodb://127.0.0.1:27017/test", {
        // useNewUrlParser: true, //使用一个新的url解析器,解决安全问题
        // useUnifiedTopology: true //使用统一新的拓扑图结构
    });

    //3.监听连接状态
    mongoose.connection.on('open', (err) => {
        if (!err) {
            console.log(`数据库连接成功`)
            resolve()
        } else {
            reject(err)
        }
    })
})
2.对规则进行约束
//操作数据库
//把数据库想象成我家的别墅
// 1.有一个帮你看门的人--请来一个保安  引入模式对象
let mongoose = require('mongoose')
let Schema = mongoose.Schema
// 2.对进入的数据进行校验--制定进入你家的规则  创建约束对象
let stuRule = new Schema({
    stu_id: {
        type: String,  //限制学号必须字符串
        required: true, //必填项
        unique: true //唯一的
    },
    name: {
        type: String,  //限制学号必须字符串
        required: true, //必填项

    },
    age: {
        type: Number,  //限制学号必须字符串
        required: true, //必填项

    },
    sex: {
        type: String,  //限制学号必须字符串
        required: true, //必填项

    },
    hobby: [String],//限制爱好只能为数组数组每一项必须字符串
    info: [Schema.Types.Mixed],  //接收所有类型
    date: {
        type: Date,
        default: Date.now()

    },
    enable_flag: {
        type: String,
        default: 'Y'
    }
})

//  3.告诉保安你的规则  创建模型对象
let stu_mode = mongoose.model('students', stuRule)//用于生成某个集合所对应的模型对象

module.exports = stu_mode
3.进行操作

const db = require('./db/db.js')
let stu_mode = require('./stu_model.js')
let index = require('./index.js')
;(async () => {
        //等待数据库连接成功
        await db
        //操作数据库
        let result = await stu_mode.findOne({ name: '班长' })
        console.log(result);
})()




express

node平台下用于快速搭建服务器的框架

不借助任何第三方库,也能在node下搭建服务器

原生搭建
/**
 * 不借助第三方库搭建node原生服务器
 *
 */
//引入node内置http模块
const http = require('http')
//创造服务员  --创建服务对象
let server = http.createServer((request, response) => {
    //让服务员干活  获取客人点的菜,联系后厨

    //1.request请求对象,里面包含客户给服务器的东西
    //2.response 响应对象,里面包含着服务器要返回给客户端的东西
    response.setHeader('content-type', 'text/html;charset=utf-8')
    response.end('<h1>我是你爸爸</h1>')
})
//指定服务器运行的端口号(绑定端口监听)
server.listen(3000, function (err) {
    if (!err) {
        console.log('服务器启动成功了');
    } else {
        console.log(err);
    }
})

在这里插入图片描述

在这里插入图片描述

express是一个基于node.js平台的简洁,灵活的web应用开发框架,它提供一系列强大特性,帮助你迅速创建各种web和移动设备

使用第三方express搭建服务器
const express = require('express')

//创建服务对象
const app = express()
//获取客户端东西,根据客户端的东西,决定返回什么内容

//配置路由 
//在nodejs我们说的路由默认都是后端路由
//路由可以理解为一组组key-value的组合
app.get('/haha', function (request, response) {
    response.send('hha')
})
app.get('/', function (request, response) {
    console.log(request.query);  //获取url里面的参数
    response.send('主页')
    //请求方式必须为get post是无效的
    //请求的uri必须为/
})
app.post('/', function (request, response) {
    response.send('主页')
    //请求方式必须为get post是无效的
    //请求的uri必须为/
})

app.listen(3000, function (err) {
    if (!err) {
        console.log('服务器启动成功了');
    } else {
        console.log(err);
    }
})

http协议

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

为什么握手三次挥手4次

握手之前还没有数据传输,确保握手就可以了

挥手之前,正在进行数据传输,为确保数据完整性,必须多经历一次验证(继续接受)

路由

route 路由

router 路由器

在这里插入图片描述

 * req.query 获取get请求查询字符串的参数,拿到的是一个对象
 * req.params  获取get请求参数的路由参数,拿到的是一个对象
 * req,body  获取post请求体,拿到的是一个对象,(要借助一个中间件)
 * req.get(xxx) 获取请求头中指定key对应的value
 
 
 
 
  response 对象
res.send() 给浏览器做出一个响应
res.end() 给浏览器做出一个响应  不会自动追加响应头
res.download() 告诉浏览器下载一个文件
res.sendFile()  给浏览器发送一个文件
res.redirect()  重定向到一个新地址(url)
res.set(header,value) 自定义响应头内容
res.get() 获取响应头指定key对应value
res.status(code)  设置响应状态码
  

在这里插入图片描述

    res.download('../package.json') //只能给一次响应
    res.sendfile(__dirname+'/index.html')  //响应一个文件 必须传递绝对路径
    res.set('demo','555')  //自定义响应体要写在send前面
    res.status(404) //自定义状态码
    res.send('ok-demo')
    console.log(res.get('X-Powered-By'))//获取响应头里面key,value 要写在send的后面很少使用
    res.redirect('http://www.baidu.com') //重定向

中间件


中间件:本质上就是一个函数,包含三个参数,request,response,next
作用:
1.执行任何代码
2.修改请求和响应对象
3.终结请求-响应循环(让一次请求得到响应)
4.调用堆栈中的和下一个中间件或路由
分类:
    1.应用(全局)中间件 (过滤非法请求,例如防盗链)
            写法1  app.use((request,response,next)=>{})
            写法2 函数定义
    2.第三方中间件(通过npm下载的中间件,例如,body-parser)
        --app.use(bodyParser.urlencoded({extended:true}))
    3.内置中间件(express内部封装好的中间件)
        --app.use(express.urlencoded({extended:true}))
        --app.use(express.static('public'))
    4.路由中间件(Router)
   
	

1.在express中定义路由和中间件的时候,根据定义顺序(代码顺序)将定义的每一个中间件或路由 放在一个数组容器中,当请求过来的时候,依次从容器中取出进行匹配,成功交给路由或中间件处理
2.对于服务器来说,一次请求,只有一个请求对象,和一个响应对象其他任何req,res都是对二者的引用

防盗链

全局中间件

全局防盗链
app.use((req,res,next)=>{
    // res.send('全局中间件给的响应')
        if(req.get('Referer')){
            let site =req.get('Referer').split('/')[2]
            if(site=='localhost:63343'){
                next()
            }else {
                res.sendFile(__dirname+'/faq03.jpg')
            }
        }else {
            next() //放行
        }
})
局部防盗链**更加灵活可以在任何需要的地方使用
function  demo( req,res,next){
    if(req.get('Referer')){
        let site =req.get('Referer').split('/')[2]
        if(site=='localhost:63343'){
            next()
        }else {
            res.sendFile(__dirname+'/faq03.jpg')
        }
    }else {
        next() //放行
    }
}

app.get('/picture',demo,(req,res)=>{
    res.sendFile(__dirname+'/sec1-5.jpg')
})

使用第三方中间件

 yarn add  body-parser
const bodyParser=require('body-parser')
//定义第三方中间件
app.use(bodyParser.urlencoded({extended:true}))
使用第三方中间件  解析post请求体中所携带的urlencoded编码形式的参数为一个对象,随后挂载到req对象上

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

使用express的第三方中间件

//使用express的第三方中间件
app.use(express.urlencoded({extended:true}))
//使用内置中间件去暴露静态资源
app.use(express.static(__dirname+'/'))

url:http://localhost:3000/index.html

router

在express里面内置了一个路由模块

//ui 路由
//创建路由器 (路由器就是一个小型的APP)
//引入router构造函数
const {Router}=require('express')
//创建路由器实例
let router= new Router()
//引入path模块  用于专门解决路径的库
const path=require('path')

router.get('/login',(req,res)=>{
    // console.log(path.resolve(__dirname,'../public/login.html'))
    res.sendFile(path.resolve(__dirname,'../public/login.html'))

})
//展示注册页面内容  //ui路由
router.get('/reg',(req,res)=>{
    // res.sendFile(__dirname+'../public/reg.html')
    res.sendFile(path.resolve(__dirname,'../public/req.html'))

})
//
module.exports=function (){
    return router
}


//引入ui路由器 login路由器
const uiRoute=require('./router/uirouter.js')
const loginRoute=require('./router/loginrouter.js')
app.use(uiRoute())
app.use(loginRoute())

服务器模板引擎

yarn add ejs
如果在express中基于node搭建服务器,使用ejs无需引入 但是要写代码
让服务器指定你用哪个模板引擎
app.set('view engine','ejs')
配置模板目录,让服务器指定你的模板在哪个目录下 在haha文件夹下找模板
app.set('views','./haha')


app.get('/show',(req,res)=>{

    res.render('show')  
    //如果哪个路由要使用show.ejs里面模板  
})

语法:

<%%>能写任意代码
<%-%> 读取后端传递过来对象指定key所对应value渲染页面 会渲染标签
<%=%> 能读取变量将内容渲染的页面  不会渲染标签

cookie

一个身份的认证

https://tool.chinaz.com/tools/urlencode.aspx cookie 的value解码

本质是一个字符串,里面包含着浏览器和服务器沟通的信息(交互时产生的信息)

存储以:key-value的形式存储

浏览器会自动携带网站的cookie,只要是该网站下的cookie全部携带

分类:

​ 会话cookie(关闭浏览器后,cookie会自动消失)

​ 持久化cookie(看过期时间,一旦时间到,自动销毁)

工作原理:当浏览器第一次请求服务器的时候,服务器可能返回一个或多个ookie

​ 浏览器判断cookie种类

​ 会话cookie:存储在浏览器运行内存上

​ 持久化cookie存储在用户的硬盘上

以后请求网站的时候,自动携带网站所以cookie

服务器拿到之前种下的cookie分析里面的内容,校验cookie合法,保存内容

应用:

​ 解决http无状态的问题(7天免登录,一般来说不会单独使用cookie,一般配合session存储)

备注:

​ cookie不一定只服务器生成,前端同样可以生成cookie,但是前端cookie没意义

存一个会话cookie  在浏览器关闭时cookie也清除
router.get('/demo1',(req, res)=>{
    //给客户端种会话cookie
    //express中给客户种cookie不需要任何的第三方插件库
    let obj={
        name:'xcl',
        age:20,
    }
    res.cookie('peiqi',JSON.stringify(obj))
    res.send('demo1的返回种了会话cookie')
})
种一个持久化cookie 在一定时间内清除
router.get('/demo2',(req, res)=>{
    //给客户端种会话cookie
    //express中给客户种cookie不需要任何的第三方插件库
    let obj={
        name:'xcl',
        age:20,
    }
    res.cookie('xcl',JSON.stringify(obj),{maxAge:1000*30}) //30秒
    res.send('demo2的返回种了持久化cookie')
})
读取cookie 要借助一个中间件 cookie-parser
yarn add cookie-parser
const cookieParser=require('cookie-parser')
app.use(cookieParser('signText'))


router.get('/demo3',(req, res)=>{
    //读取客户端携带的cookie 用一个库 cookie-parser
    console.log(req.cookies);
    let {xcl}=req.cookies
    let aa=JSON.parse(xcl)
    res.send(`demo3的返回种了持久化cookie${aa.name}`)
})
删除一个cookie
router.get('/demo4',(req, res)=>{
   res.cookie('xcl','',{maxAge:0})//方法一
    res.clearCookie('xcl')  //方法二

})

cookie与session配合

在这里插入图片描述

//session
/*
    标准来说session指的是会话,服务器session会话存储

    特点:存储在服务端
        存储的是浏览器和服务器之间产生的沟通的信息

     默认session存储在服务器内存中,没个客户端发来请求,服务器就会开辟一个空间,提供session存储使用

     流程:
        第一次浏览器请求服务器的时候,服务器会开辟出一块内存空间,提供session使用
        返回响应的时候,会自动返回一个cookie cookie包含着会话存储容器的编号
        以后请求的时候,会自动携带这个cookie给服务器
        服务器从该cookie中拿到的session的id进行匹配
        服务器会根据匹配信息决定下一步逻辑

     一般来说,cookie会搭配session使用
     服务端一般会做session持久化,防止服务器重启,造成session丢失
 */

当第一次浏览器访问服务器的时候,服务器会为本次请求开启session会话存储空间,存储记录随后对session进行加密编号 ,把编号放在cookie里,把cookie返回给客户端,以后客户端的cookie存的是session的编号,服务器拿到编号进行匹配如成功则渲染,没对应上重新登录

const session=require('express-session')
app.use(session({
    name:'userid',
    secret:'atguigu',
    cookie:{
        maxAge:1000*30
    }
}))   server引入session模块


 console.log(data._id.toString())
  req.session._id=data._id.toString()
业务路由把数据库里面_id 加入到session里面
 const {_id}=req.session  //ui路由就能获取加密了的_id
    if(_id){
        console.log(_id)
        userModule.findOne({_id},(err,data)=>{
        res.send(`登录成功你的名字是${data.name}`)
        })

    }else {
        res.redirect('/login')
    }

session持久化 想让服务器重启session依然有效

//server.js引入用于session持久化 
const MongoStore=require('connect-mongo')

app.use(session({
    name:'userid',
    secret:'atguigu',
    saveUninitialized:false,//是否在存储内容之前创建session会话
    resave:true,//是否在每次请求时,强制重新保存session,即使她没变化(保险)
    store:MongoStore.create({
        mongoUrl:'mongodb://localhost:27017/session',
        touchAfter:24*3600  //修改频率24小时只更新一次
    }),
    cookie:{
        maxAge:1000*30
    }
}))

加密技术

yarn add md5
const md5=require('md5') 引入
pwd:md5(pwd)  //把密码转换为MD5加密

yarn add sha1
const sha1=require('md5') 引入
pwd:sha1(pwd)  //把密码转换为sha1加密

ajax

在这里插入图片描述

let xhr=new XMLHttpRequest()
xhr.onreadystatechange=function(){
	if(xhr.readyState==4&&xhr.status==200){
		console.log(xhr.response)
		
	}
}
xhr.open('get','http://localhost:3000/axax_get')
xhr.send();

接口跨域

npm i cors
const  cors=require('cors')
app.use(cors())
一定要在路由前面配置

token

jwt三个部分组成:header,payload,signature

payload,才是真正用户信息

其他两个,是安全性部分,保证token安全性

安装jwt包
npm i jsonwebtoken express-jwt
第一个生成jwt字符串
第二个将jwt字符串解析还原成json对象

const  jwt=require('jsonwebtoken');
const  expressjwt=require('express-jwt');

token:jwt.sign({username:userinfo.username},secretkey,{expiresin:"30s"}) 生成token字符串

解密
app.use(expressjwt({ secret:secretkey, algorithms: ["HS256"] }).unless({path: ['/register'] }))


```javascript

为保证jwt字符串安全性,避免被破解,需要指定secret密钥
当生成jwt字符串时候,需要使用secret密钥加密
当把jwt解析还原成json时候,需要使用secret解密
const secretkey='itheimano1'

在这里插入图片描述


router.use((err,req,res,next)=>{
if (err.name==‘UnauthorizedError’){在这里插入代码片
return res.send({mes:“无效token”})
}
})
//全局路由判断是否有token否则无效


抽离用户模块和处理函数

const api_handler=require('./router_handler/api') //引入
router.get('/my',api_handler.my)  //api模块

exports.my=(req,res)=>{
    console.log(req.auth)

    res.send({
        status:1,
        msg:"登录成功",
        data:req.auth,


    })
}  //抽离的处理函数

封装res.cc

//封装res.cc函数
app.use((req,res,next)=>{
    res.cc=function (err,status=0){
        res.send({
            status,
            msg:err instanceof Error ? err.message:err,
        })
    }
    next()
})

表单数据合法验证

npm i @hapi/joi@17.1.0   为表单携带的每一个数据项定义验证规则
npm i @escook/express-joi  实现自动对表单数据进行验证功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值