node 缓存

128 阅读3分钟

目录结构

目录结构.png

准备工作: npm init npm i express jsonwebtoken express-jwt

登录.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>首页</title>
</head>
<body>
    <div>
        <span>用户名:</span>
        <input type="text" id="userInp">
    </div>
    <div>
        <span>密码:</span>
        <input type="password" id="passInp">
    </div>
    <div>
        <button id="btn">登录</button>
    </div>
    <script src="./js/axios.min.js"></script>
    <script src="./js/jquery3.5.1.js"></script>
    <script>
        $("#btn").on("click", () => {
            var username = $("#userInp").val();
            var password = $("#passInp").val();
            axios({
                url: "http://localhost:3000/api/login",
                params: {
                    username,
                    password
                }
            }).then(res => {
                if (res.data.status == 1) {
                    window.location.href = "./首页.html";
                }
            })
        })
    </script>
</body>
</html>

首页.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>首页</title>
</head>

<body>
    <div id="myDiv"></div>
    <button id="outBtn">退出-再刷新就没了</button>
    <script src="./js/axios.min.js"></script>
    <script src="./js/jquery3.5.1.js"></script>
    <script>
        axios({
            url: "http://localhost:3000/api/getMoney"
        }).then(res => {
            $("#myDiv").html(res.data.data);
        })

        $("#outBtn").on("click", () => {
            axios({
                method: "PUT",
                url: "http://localhost:3000/logout"
            }).then(res => {
                alert(res.data.msg);
                window.location.reload();
            })
        })
    </script>
</body>

</html>

22.3_Cookie机制.js

const express = require('express')
const app = express()

app.use(express.static(__dirname + '/public'))

// 模拟用户注册成功的已存在的用户名和密码
let arr = [
  {
    username: 'lcz',
    password: 111111,
    money: 10000,
  },
  {
    username: 'xiaoze',
    password: 222222,
    money: 500,
  },
]
// 重要: 跨域后端无法设置前端cookie - 直接在浏览器打开后端的静态资源

// 服务器端, 利用响应头给前端本次请求的位置设置cookie的方式
app.get('/api/login', (req, res) => {
  // 假装登录成功了, 设置一个cookie给前端, 比如用户名字
  // set-cookie是固定的, 后面的格式固定名称=值 - 去浏览器请求这个接口-观察前端浏览器上被设置了cookie
  let { username, password } = req.query
  // 查找用户和密码是否有同时匹配的
  const have = arr.some(
    (obj) => obj.username == username && obj.password == password
  )
  if (have) {
    res.setHeader('set-cookie', `user=${username}; path=/`)
    // path代表此cookie在前端生效的区域(发送请求时url只要是在/下, 就都能使用cookie)
    res.send({
      status: 1,
      msg: '登录成功',
    })
  } else {
    res.send({
      status: 0,
      msg: '账号或密码错误',
    })
  }
})

// 登录请求-> res返回header 信息(cookie)->客户端
// 再次发请求->自动将cookie放在该请求的请求头中!
app.get('/api/getMoney', (req, res) => {
  // 提取cookie, 找到user保存的用户名
  let argStr = []
  if (req.headers.cookie) {
    argStr = req.headers.cookie.split('; ')
  }
  let username = '' // 保存找到的用户名
  argStr.forEach((str) => {
    let smallArr = str.split('=')
    if (smallArr[0] == 'user') {
      username = smallArr[1]
    }
  })
  // 再用用户名, 查询这个用户的金额
  let money = 0
  arr.forEach((obj) => {
    if (obj.username == username) {
      money = obj.money
    }
  })
  res.send({
    status: 1,
    msg: '获取成功',
    data: money,
  })
})

app.listen(3000, () => {
  console.log('服务器启动了')
})

22.4_Session机制.js

const express = require('express')
const app = express()

app.use(express.static(__dirname + '/public'))

let arr = [
  {
    username: 'lcz',
    password: 111111,
    money: 10000,
  },
  {
    username: 'xiaoze',
    password: 222222,
    money: 500,
  },
]

// express-session实现session技术
const session = require('express-session')
app.use(
  session({
    secret: 'keyboard cat', // 用于加密目标数据用的字符串
    resave: false, // resave是指每次请求都重新设置session cookie
    saveUninitialized: true, // saveUninitialized是指无论有没有session cookie,
    // 每次请求都设置个session cookie ,默认给个标示为 connect.sid
  })
)

app.get('/api/login', (req, res) => {
  let { username, password } = req.query
  // 查找用户和密码是否有同时匹配的
  const have = arr.some(
    (obj) => obj.username == username && obj.password == password
  )
  if (have) {
    // 1 将当前正确的用户的信息保存在内存中
    req.session.usern = username
    res.send({
      status: 1,
      msg: '登录成功',
    })
  } else {
    res.send({
      status: 0,
      msg: '账号或密码错误',
    })
  }
})

// 重要 - 多个前端登录验证, 需要用不同的浏览器, 因为一个浏览器的同一个域名下的cookie会被覆盖
app.get('/api/getMoney', (req, res) => {
  // 提取cookie的值, 从express-session内存中提取对应的值
  const username = req.session.usern
  console.log(username); // 当前登录的用户名对应的值
  // 查找余额
  let money = 0
  arr.forEach((obj) => {
    // 刷卡认证 -> 本人持卡
    if (obj.username == username) {
      money = obj.money
    }
  })

  res.send({
    status: 1,
    msg: '获取成功',
    data: money,
  })
})

app.listen(3000, () => {
  console.log('服务器启动了')
})

22.5_删除Session.js

const express = require("express");
const app = express();
app.listen(3000, () => {
    console.log("服务器启动了");
})
app.use(express.static(__dirname + "/../1_前端/"));

let arr = [
    {
        username: "lidongxu",
        password: 111111,
        money: 10000
    },
    {
        username: "xiaochuan",
        password: 222222,
        money: 500
    }
]

const session = require("express-session");
app.use(session({
    secret: 'keyboard cat', 
    resave: false, 
    saveUninitialized: true
}))

app.get("/api/login", (req, res) => {
    let {username, password} = req.query;
    const have = arr.some(obj => obj.username == username && obj.password == password);
    if (have) {
        req.session.usern = username;
        res.send({
            status: 1,
            msg: "登录成功"
        })
    } else {
        res.send({
            status: 0,
            msg: "账号或密码错误"
        })
    }
})

app.get("/api/getMoney", (req, res) => {
    const username = req.session.usern;
    let money = 0;
    arr.forEach(obj => {
        if (obj.username == username) {
            money = obj.money;
        }
    })
    res.send({
        status: 1,
        msg: "获取成功",
        data: money
    })
})

app.put("/logout", (req, res) => {
    req.session.destroy();
    res.send({
        status: 1,
        msg: "退出成功"
    })
})

23.0_jwt基础使用.js

const express = require("express");
const app = express();

// 服务端渲染: session-cookie -> 跨域 cookie用不了->
// 前后端分离(跨域)->jwt.

app.use(express.static(__dirname + "/assets"));

let arr = [
  {
    username: "lcz",
    password: 111111,
    money: 10000,
  },
  {
    username: "xiaoze",
    password: 222222,
    money: 500,
  },
];

// 1. 引入模块
const jsonwebtoken = require("jsonwebtoken");
const expressJwt = require("express-jwt");

// 2. 设置秘钥
const secretKey = "itheima No.1 ^.^"; // 钥匙

// 4. 解析 jwt
// 用哪个秘钥解密,
// jwt的算法->HS256
// unless哪些接口不需要权限验证
app.use(
  expressJwt({
    secret: secretKey,
    algorithms: ["HS256"],
  }).unless({
    path: [/^\/api\//],
  })
);

app.get("/api/login", (req, res) => {
  let { username, password } = req.query;
  const have = arr.some(
    (obj) => obj.username == username && obj.password == password
  );

  if (have) {
    // 3. 登录成功 - 生成token
    res.send({
      status: 1,
      msg: "登录成功",
      // 注意这个前缀是expressJwt规定的, 必须带这个固定的头加空格, 里面要拆分使用(跟真正jwt数据毫无关系)
      // 客户端代码 -> 大事件login->res.data.data.token
      token:
        "Bearer " +
        jsonwebtoken.sign({ username: username }, secretKey, {
          // 设置token的有效时长
          expiresIn: "24h",
        }),
    });
    // h是小时, s是秒
  } else {
    res.send({
      status: 0,
      msg: "账号或密码错误",
    });
  }
});

app.get("/my/getMoney", (req, res) => {
  // 5. 使用req.user.username
  const username = req.user.username;
  let money = 0;
  arr.forEach((obj) => {
    if (obj.username == username) {
      money = obj.money;
    }
  });
  res.send({
    status: 1,
    msg: "获取成功",
    data: money,
  });
});

// 6. 兜底错误处理 - 自定义错误处理中间件
app.use((err, req, res, next) => {
  // token 解析失败导致的错误
  // UnauthorizedError
  if (err.name == "UnauthorizedError") {
    return res.send({ status: 401, msg: "无效的token" });
  }

  res.send({ status: 500, msg: err.message });
});

app.listen(3000, () => {
  console.log("服务器启动了");
});