token
thought
Log records in the server does not need to store the user's all there is to the client the client's own memory (cookie, local)
1, the client uses the user name with password logon request
2, the server receives the request, to verify the user name and password
3. After successful authentication, the server will issue a Token (plus a string of secret), then the Token sent to the client
4, after the client receives the Token it can be stored, such as on a Cookie or Local storage in
5, each time a client requests a resource to the server needs with the server issued Token
6, data server receives the request, and then to verify that the client requests inside with the Token, if authentication is successful, it is returned to the client's request
achieve
jsonwebtoken installation introduced
let jwt = require('jsonwebtoken')
Generating a signature
let token = jwt.sign(payload, secretOrPrivateKey, [options, callback])
Verification token
jwt.verify(token, secretOrPublicKey, [options, callback])
token delete
There are clients, responsible for deleting
session vs token
session | token | |
---|---|---|
The server store user information | √ | × |
Avoid CSRF attacks | × | √ |
Installation of | general | high |
Multi-server sticky problem | presence | does not exist |
Multi-server sticky problem
When reading session in the application, write or delete operation, there will be a file operation occurs in the operating system's temp folders, at least when the first time. Suppose you have multiple servers and create a session on the first service. When you send the request again and this request falls on another server, session information does not exist and will be given a "non-certified" in response. I know that you can solve this problem through a session stickiness. However, token-based authentication, this problem was solved naturally. Not sticky session problem because the token will be sent to the server for each request in the request is intercepted
Example:
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:"库数据"
})
}
})
})
File Upload
thought
Front-end forms -> back-end receiving the file itself -> saved on the server -> database to record some information about the file -> Library to return to the nodejs relevant information - the front> nodejs return to
前端: <input type=file enctype=“multipart/form-data” name=“fieldname”
achieve
multer-> file name will be randomly -> fs module renamed -> path system module parses the disk path
Rear: multer form-data receiving encoded data
path system module
Operating system disk path
coding
windows: c:\\user\\admin\\a.jpg
mac: ~/desktop/1901
UI presents
windows: c:\user\admin
mac: ~/desktop/1901
API
Disk path resolution parse
path.parse('c:\\wamp\\xx.png') // string -> object
//返回
{
root: 'c:\\', 盘符
dir: 'c:\\wamp', 目录
base: 'xx.png', 文件名
ext: '.png', 扩展名
name: 'xx' 文件,不含扩展名
}
The combined fragments join
path.join('磁盘路径1','磁盘路径2','磁盘路径n')
__dirname magic variable returns disk path of the current file
The combined fragments resolve
path.resolve('磁盘路径1','磁盘路径n')
Merge the disk fragment, right to left to find the root, left to right stitching, no root is found, the current directory is the root file
Example:
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 Middleware
multer form-data receiving encoded data, note that when carrying all requirements at the front end, such as: <input type=file enctype="multipart/form-data" name="fieldname"
,
use
//1 引入
let multer = require('multer');
//2 实例化
let objMulter = multer({ dest: './upload' }); //dest: 指定 保存位置(存到服务器)
//安装中间件,
app.use(objMulter.any()); //允许上传什么类型文件,any 代表任何类型
Req request body extends middleware req.files
app.get('/reg',(req,res)=>{
req.files
})
fieldname: Form name name
originalname: filename uploaded
encoding: encoding
mimetype: File type
buffer: the file itself is
size: the size of
destination: save path
filename: After saving the file name without the suffix
save the file to save the disk path +: path name without suffix
Example:
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
})
})
Rendering backend
Usually based on json data returned by the backend, and then generate html rendering is called front-end, back-end rendering and is returned to the browser after the rear end of the combine json with html rendering is good, no matter what the front end
Template engine
No matter who before and after rendering the page, will be used template engine, front-end rendering the page is actually operating dom , the back-end rendering the page is the character data and html stitching after threw browser
engine | front end | rear end |
---|---|---|
AngularJS | √ | × |
vue/mustach | √ | √ |
react | √ | √ |
angularTs/mustach | √ | √ |
jade/pug | × | √ |
ejs | × | √ |
jquery + art-template | √ | × |
handlerbars | √ | × |
jade
Principle : fs grab the front page + jade + static data -> Back send (data) -> Browser
Features : invasive, strong dependence
use
let jade = require('jade')
let html = jade.renderFile('jade模板文件',{数据},{pretty:true}); //返回字符
jade template file syntax
Father and son to indent
attributes: Label (key = value, key2 = value )
Content: Content Tags
Example:
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
Principle : fs grab the front page + ejs + static data -> Back send (data) -> Browser
Features : non-invasive, moderate, weak dependence
use
let ejs = require('ejs')
ejs.renderFile('ejs模板文件',{要合并到html数据},回调(err,data))
err: error, null means no error
data: the rendered characters | flow
ejs Template: suffix of html file named ejs
ejs template file syntax
- ejs structure is html
- Output: <data name =% | attribute names | + expression variable name%>
- Statement: <% statement%> to be <%%> parcel
- Non-escape output: <% - Data Name | Variable name + expression%>
- Public Loading: <% - include ( './ hd.ejs', { data})%>
Other extensions
Example:
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>