nodejs基础-4

token

思想

在服务端不需要存储用户的登录记录,全部发给客户端有客户端自己存(cookie,local)

1、客户端使用用户名跟密码请求登录
2、服务端收到请求,去验证用户名与密码
3、验证成功后,服务端会签发一个 Token(加了密的字符串),再把这个 Token 发送给客户端
4、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

实现

jsonwebtoken的安装引入

let jwt = require('jsonwebtoken')

生成签名

let token = jwt.sign(payload, secretOrPrivateKey, [options, callback])

校验token

jwt.verify(token, secretOrPublicKey, [options, callback])

token删除

有客户端,负责删除

session vs token

session token
服务端保存用户信息 ×
避免CSRF攻击 ×
安装性 一般
多服务器粘性问题 存在 不存在

多服务器粘性问题

当在应用中进行 session的读,写或者删除操作时,会有一个文件操作发生在操作系统的temp 文件夹下,至少在第一次时。假设有多台服务器并且 session 在第一台服务上创建。当你再次发送请求并且这个请求落在另一台服务器上,session 信息并不存在并且会获得一个“未认证”的响应。我知道,你可以通过一个粘性 session 解决这个问题。然而,在基于 token 的认证中,这个问题很自然就被解决了。没有粘性 session 的问题,因为在每个发送到服务器的请求中这个请求的 token 都会被拦截

实例:

let express= require("express")

let app = express()
//引入jsonwebtoken模块
let jwt =require("jsonwebtoken")

app.listen(3000,()=>console.log("端口监听中"))

app.get("/api/login",(req,res)=>{

    //获取username,password 进行数据库验证
    //生产token
   let token= jwt.sign({

        username:req.query.username

    },"MD5",{expiresIn:60})//加密方式 过期时间

    
    console.log(token)

    //token和库信息返回给前端
    res.send({
        err:0,
        msg:"用户登录了",
        data:"库数据",
        token
    })
})


app.get("/api/user",(req,res)=>{

    //获取客户端传递过来的token
    let token = req.query.token || req.body.token || req.headers.token;
    
    //验证token
    jwt.verify(token,"MD5",(err,decode)=>{
        // console.log("err",err)
        console.log("decode",decode)

        if(err){
            //验证失败
            res.send({
                err:1,
                msg:"登录失败"
            })
        }else{
            //验证成功 返回数据
            res.send({
                err:0,
                msg:"登录成功",
                data:"库数据"
            })
        }
    })

})

文件上传

思想

前端表单->后端接收到文件本身->保存到服务器上->给数据库记录文件一些信息->库返回给nodejs相关信息->nodejs返回给前端

前端: <input type=file enctype=“multipart/form-data” name=“fieldname”

实现

multer->文件名会随机->fs模块改名->path系统模块解析磁盘路径

后端:multer 接受 form-data编码数据

path系统模块

操作系统磁盘路径

编码

windows: c:\\user\\admin\\a.jpg

mac: ~/desktop/1901

UI呈现

windows: c:\user\admin
mac: ~/desktop/1901

API

磁盘路径解析 parse

path.parse('c:\\wamp\\xx.png') // string -> object

//返回
{
   root: 'c:\\', 盘符
   dir: 'c:\\wamp', 目录
   base: 'xx.png',  文件名
   ext: '.png', 扩展名
   name: 'xx' 	文件,不含扩展名
}

片段合并join

path.join('磁盘路径1','磁盘路径2''磁盘路径n')

__dirname 魔术变量 返回当前文件所在的磁盘路径

片段合并 resolve

path.resolve('磁盘路径1','磁盘路径n')

合并磁盘片段,右到左找根,左到右拼接,没有找到根,以当前文件路径为根

实例:

const path = require("path")

// let str = "F:\\path\\idCard2.jpg"

let str ="F:/path/idCard2.jpg"

//path解析 路径
console.log(path.parse(str))

// {
//     root: 'F:/',
//     dir: 'F:/path',
//     base: 'idCard2.jpg',
//     ext: '.jpg',
//     name: 'idCard2'
//   }

let str1 ="F:\\path"
let str2 ="idCard2.jpg"

console.log(path.join(str1,str2))
//F:\path\idCard2.jpg


//node.js全局变量 __dirname 获取当前文件路径
// console.log(__dirname)

// console.log(path.join(__dirname,str2))


//片段合并 resolve

// console.log(path.resolve(str2)) //相当于path.join(__dirname,str2)

console.log(path.resolve("f:\\",str2)) //f:\idCard2.jpg

console.log(path.resolve("a","f:\\","b","c.jpg"))//f:\b\c.jpg  从后往前去找根目录 找到了之后从前往后排列

multer中间件

multer 接受 form-data编码数据,所有要求前端携带时注意一下,如:<input type=file enctype="multipart/form-data" name="fieldname",

使用

//1 引入
let multer  = require('multer');
//2 实例化  
let objMulter = multer({ dest: './upload' }); //dest: 指定 保存位置(存到服务器)
//安装中间件, 
app.use(objMulter.any());  //允许上传什么类型文件,any 代表任何类型 

中间件扩展了req请求体 req.files

app.get('/reg',(req,res)=>{
  req.files
})

fieldname: 表单name名
originalname: 上传的文件名
encoding: 编码方式
mimetype: 文件类型
buffer: 文件本身
size:尺寸
destination: 保存路径
filename: 保存后的文件名 不含后缀
path: 保存磁盘路径+保存后的文件名 不含后缀

实例:

const express = require("express")
const fs = require("fs")
const path = require("path")
const app = express()
app.listen(3000,()=>console.log("3000端口在监听中哦...."))

//静态资源托管  http://localhost:3000/upload/XXXXXXXXXXXXXX.webp
//如果用户想要在浏览器上面直接访问图片或者html页面,需要做一个静态服务器。  
app.use(express.static("./public"))

//文件上传  前端例如上传一张图片给后端,后端需要将图片存入upload文件夹里面去。
//1.引入multer中间件
const multer = require("multer")

//2.实例化multer
let objMulter = multer({ dest: './public/upload' }); //dest: 指定 保存位置(存到服务器)

//3.安装中间件
//app.use(objeMulter.image())  //仅允许上传图片类型
app.use(objMulter.any())  //运行上传什么类型的文件,any就代表任意类型都可以


app.post("/api/reg",(req,res)=>{
    // console.log(req)
    // console.log(req.files[0].originalname)

    //4.需要进行文件的改名操作了
    // fs.renameSync('改前','改后');
    let oldFile = req.files[0].path;
    let newFile = req.files[0].path + path.parse(req.files[0].originalname).ext;
    fs.renameSync(oldFile,newFile)

    //5.把磁盘路径转成网络路径入库操作

    //6.可以将地址返回给客户端
    res.send({
        err:0,
        url:"http://localhost:3000/upload/"+req.files[0].filename+path.parse(req.files[0].originalname).ext
    })
})

后端渲染

通常根据后端返回的json数据,然后来生成html被称为前端渲染,而后端渲染是后端把json与html结合渲染好后返回到浏览器,没前端什么事了

模板引擎

无论前后谁来渲染页面,都会用到模板引擎,前端渲染页面实际上是操作dom,后端渲染页面是把数据和html字符拼接后丢给浏览器

引擎 前端 后端
angularJs ×
vue/mustach
react
angularTs/mustach
jade/pug ×
ejs ×
jquery + art-template ×
handlerbars ×

jade

原理:fs抓取前端静态页面 + jade + 数据 -> 返回send(data) -> 浏览器

特点:侵入式,强依赖

使用

let jade = require('jade')
let html = jade.renderFile('jade模板文件'{数据}{pretty:true});	//返回字符

jade模板文件语法

父子要缩进
属性: 标签(key=value,key2=value)
内容: 标签 内容

其他扩展

实例:

const express = require("express")
//引入jade
const jade = require("jade")
const app = express()
app.listen(3000)


app.get("/",(req,res)=>{
    //通过jade模板引擎渲染文件
    //let html = jade.renderFile('jade模板文件'{pretty:true,key:value});	//返回字符
    
    let html = jade.renderFile("./views/jade/index.jade",{pretty:true,data:"你好呀,jade!"})
    console.log(html) 
    res.send(html)
})

index.jade

html
    head
    body
        div(class="list")
            ul
                li(class="active")
                    a(href="http://www.baidu.com") a连接....

        div 我是div哦... 
            h1 #{data}

ejs

原理:fs抓取前端静态页面 + ejs + 数据 -> 返回send(data) -> 浏览器

特点:非侵入式,温和,弱依赖

使用

let ejs = require('ejs')
ejs.renderFile('ejs模板文件',{要合并到html数据},回调(err,data))

err:错误,null代表没有错误

data: 渲染后的字符|流

ejs模板 : 后缀名为ejs的html文件

ejs模板文件语法

  • ejs 结构就是html
  • 输出: <%= 数据名|属性名|变量名 + 表达式 %>
  • 语句: <% 语句 %> 需要被<% %> 包裹
  • 非转义输出: <%- 数据名|变量名 + 表达式 %>
  • 载入公共:<%- include(’./hd.ejs’,{数据}) %>
    其他扩展

实例:


const express = require("express")
//引入ejs模板引擎
let ejs = require("ejs")

const app = express()
app.listen(3000)

app.use(express.static("./public"))

let data = {
    title:"hello!!ejs模板...",
    age:18,
    bool:false,
    list:[
        {id:1,des:"123,123",href:"href1"},
        {id:2,des:"456,456",href:"href2"},S
        {id:3,des:"789,789",href:"href3"}
    ],
    strong:"<strong>Strong</strong>" 
}  

app.get("/",(req,res)=>{
    ejs.renderFile("./views/ejs/index.ejs",data,(err,data)=>{
        
        console.log("data=>",data) 
        if(!err){
            res.send(data)
        }
    })  
})

index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%-strong %></title>
    <link rel="stylesheet" href="/css/style.css">
</head>
<body>  

    <%- include('./hd.ejs',{title:"你好"}) %>

    <h1><%=title %></h1>
    <h3><%=age+1 %></h3>

    <%
        var a = 3
        var b = 4
        var c = a+b
    %>
    <% var d = 10 %>
    <% var e = 20 %>
    <% f = d+e %>

    <% if(bool){%>
        <nav>渲染nav1这个导航....</nav>
    <% }else{ %>
        <nav>渲染nav2这个导航....</nav>
    <%}%>

    <div>c====> <%=c %></div>
    <div>c====> <%=f %></div>

    <ul>
        <% for(var i=0;i<list.length;i++){ %>
            <li><a href="<%= list[i].href%>"><%=list[i].des %></a></li>
        <% } %>
        
    </ul>


    <div>
        <% for(var i=0;i<list.length;i++){ %>
            <p><a href="<%= list[i].href%>"><%=list[i].des %></a></p>
        <% } %>
    </div>
</body>
</html>
发布了21 篇原创文章 · 获赞 0 · 访问量 301

猜你喜欢

转载自blog.csdn.net/weixin_43861707/article/details/104831003
今日推荐