4

NODE基于express 框架和mongoDB完成session认证 和图片上传删除等功能 - 乔木滴滴

 2 years ago
source link: https://www.cnblogs.com/qiaomucreate/p/16697678.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

https://gitee.com/zyqwasd/mongdbSession

本项目的mongodb是本地的mongodb 开启方法可以百度一下 端口是默认的27017

1. 注册登录页 

2969767-20220915190521829-332995109.png
2969767-20220915190539466-1009768516.png

 2. 上传的图片 和删除数据库的数据和服务器上的图片

 

2969767-20220915190609041-722304640.png

 前端代码 因为是个小项目就用原生写了 

1. 这个是login 页面一个注册模块一个登录模块

 <!-- 引入axios 方便操作 -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
    //--------------------- 页面的切换
    const registerPage = document.querySelector(".register")
    const loginPage = document.querySelector(".login")
    register.onclick = () => {
        loginPage.style.display = "none"
        registerPage.style.display = "block"
    }
    login.onclick = () => {
        loginPage.style.display = "block"
        registerPage.style.display = "none"
    }
    //-----------------------注册页
    reg_submit.onclick = () => {
        if (!(reg_username.value) && !reg_password.value)
            return alert("不能为空");
        const fd = new FormData()// 创建一个表单 把数据放进去 发给后端
        fd.append("avatar", file.files[0]);
        fd.append("password", reg_password.value)
        fd.append("username", reg_username.value)
        // 发送头像和用户名密码去注册
        axios.post("/login", fd).then(res => {
            alert("注册" + (res.data.ok ? "成功" : "失败"))
            location.reload();
        })
    }
    // ----------------------登录页
    submit.onclick = () => {
        if (!(username.value) && !password.value)
            return alert("不能为空");
        axios.post("/login/find", {
            username: username.value,
            password: password.value
        })
            .then(res => {
                console.log(res.data)
                if (res.data.ok) { //设置username 和 头像便于首页显示
                    localStorage.setItem("username", username.value)
                    localStorage.setItem("avatar", res.data.avatar)
                    location.href = '/'
                } else {
                    alert("密码错误")
                }
            })
    }
</script>

 2. 首页代码

 fetch("/api")
    .then(res => res.json())
    .then(res => {
      render(res)
    })
  username.innerHTML = localStorage.getItem("username")
  img.src = localStorage.getItem("avatar")
  function render(arr) {//渲染页面 
    table.innerHTML = arr.map((item, index) => ` 
    <tr id='${item._id}' data-src='${item.avatar}'>
      <td>${index}</td>
      <td>${item.username}</td>
      <td><img src="${item.avatar}" alt=""></td>
      <td><button id='del'>del</button></td>
    </tr>
    `).join("")
  }
  table.onclick = (e) => {
    if (e.target.nodeName === "BUTTON") {
      const parent = e.target.parentNode.parentNode
      const src = parent.dataset.src
      // 发请求删除对应数据库的内容
      fetch(`/api?id=${parent.id}&src=${src} `, { method: 'delete' })
        .then(res => res.json()).then(res => {
          // 删除对应的tr 
          res.ok && parent.remove()
        })
    }
  }

1. 因为时间问题就用了express生成器 可以去expresse 官网查看 获取下载我的代码

连接mongodb

1. 创建一个配置文件夹config 下载安装mongoose 模块 连接数据库 (一定要先开启数据库)

const mongoose = require("mongoose");
// 因为是演示就自己在本地搭了一个数据库
// 连接好了数据库并且 创建了一个叫users 的数据库
mongoose.connect("mongodb://127.0.0.1:27017/users")

2. 在www 文件下引入

// 引入数据库
require("../config/mongoose")

3. 因为mongodb的数据自由度高所有配置一个模板来规定数据类型  在model文件夹/userModel

const mongoose = require("mongoose")
// 定义数据类型
const modelType = {
    username: String,
    password: String,
    avatar: String,
}

const userModel = mongoose.model("user", new mongoose.Schema(modelType));

module.exports = userModel

配置multer 模块在app.js中的代码

1.在app 中引入multer模块来处理数据和配置文件下载的路径 

// 引入multer
const multer = require("multer")
// 部署放头像的文件
const upload = multer({ dest: "public/uploads/" })

2. 在app 中处理login 上传来的图片把他放入到指定文件夹中  如果想知道如何上传多个文件可以私聊我

// 处理文件上传数据 single 是上传单个文件 array是上传多个文件
app.use("/login", upload.single("avatar"), loginRouter);

配置session 在app.js中代码

1. 在app.js中引入express-session 和 connect-mongo 

// 引入session 模块
const session = require("express-session");
// 引入  connect-mongo 这个是存储cookie 到mongodb 中自动删除和更新
const MongoStore = require("connect-mongo")

2.配置初始化配置session 

// 配置session 
app.use(session({
  name: "mySession",
  secret: "session secret",//配置秘钥
  resave: true,//重新设置cookie 值可以重新计时
  saveUninitialized: true,//初始化session  一开始就给服务器发送一个cookie 
  cookie: {
    maxAge: 1000 * 60 * 60, //设置过期时间
    secure: false,//是否在安全模式下就是https 下访问
  },
  rolling: true,//表示在超时前刷新就会从新计时cookie 为false 表示超时前刷新多少次都会按照第一次开始计时
  // 配置cookie 存入到MongoDB 中
  store: MongoStore.create({
    mongoUrl: 'mongodb://127.0.0.1:27017/my_session',//链接数据库
    ttl: 1000 * 60 * 60, //设置过期时间
  })
}))

3. 全局拦截认证session

// 全局拦截session 
app.use((req, res, next) => {
  if (req.url.includes("login")) return next()
  // 登录成功了就给session挂载一个user属性
  if (req.session.user) {
    // 如果有就放行重新设置session 值
    req.session.myDate = Date.now();
    next()
  } else {
    // 因为我是又有后端渲染又有前端的请求所以我们要判断
    req.url.includes("api") ?
      // 如果是api 就send  ok:1
      res.status(401).send({ ok: 1 })
      // 如果是 页面的请求就跳到login 页面
      : res.redirect("/login")
  }
})

处理login页面数据

1. 在router中的路径处理

const express = require("express");
const controller = require('../controller/userController');
const router = express.Router()

router.get("/", (req, res) => {
    res.render("login")
})

// 注册来的数据
router.post("/", controller.create)
// 登录来的数据
router.post("/find", controller.find)

module.exports = router

处理数据响应每一个接口的处理函数 因为代码少就没有多分

const userService = require("../service/userService")
const controller = {
    // 创建数据到mongodb中注册页传来的
    async create(req, res) {
        // 数据解构出来
        const { username, password } = req.body
        // 如果上传头像就存储上传来的 
        // 如果没有上传来就走默认头像
        const avatar = req.file ?
            "/uploads/" + req.file.filename :
            "/images/avatar.jpeg";
        // 去service模块创建数据到数据库中
        await userService.create(username, password, avatar);
        // 返回前端数据
        res.send({ ok: 1 })
    },
    async find(req, res) {
        const { username, password } = req.body;
        // 用async  和await 来去数据库查找数据 主要代码在service中
        let data = await userService.find(username, password)
        if (data.length) {
            // 如果验证通过了就设置一个session值
            req.session.user = data[0]
            // 如果找到了 返回前端一个当前登录用户的头像
            res.send({ ok: 1, avatar: data[0].avatar })
        } else {
            res.send({ ok: 0 })
        }
    },
    // 查找所有数据用来渲染主页 显示页面 因为都是异步的所以用了async 和await 
    async findAll(req, res) {
        let data = await userService.findAll()
        res.send(data)
    },
    // 前端发来的删除用户请求
    async delete(req, res) {
        // 把id 和图片的src 结构出来
        const { id, src } = req.query
        // 去删除数据库中的数据
        let data = await userService.delete(id)
        // 去删除本地文件 因为代码少懒得分一个模块了
        await userService.deleteFile(src)
        // 给前端传一个布尔值这个如果删除了就是true 没有就是false
        res.send({ ok: data.acknowledged })
    }
}

module.exports = controller

处理数据库和文件夹中的数据

const userModel = require("../model/userModel")
// 引入fs 模块 因为是异步所以要用promises
const fs = require("fs").promises
const service = {
    // 把数据存储到数据库中
    create(username, password, avatar) {
        // 用我们之前的模板直接来创建数据
        return userModel.create({
            username, password, avatar,
        })
    },
    find(username, password) {
        // 查找数据给前面模块返回回去 条件是传来的值
        return userModel.find({ username, password })
    },
    findAll() {
        // 只获取到["username", "avatar"]两个字段
        return userModel.find({}, ["username", "avatar"])
        // 当然因为数据量少没有搞分页什么的
        // find().count()是获取总的条数
        // sort() 按照什么排序
        // skip ()跳过几条
        // limit() 要几条 
        // 也蛮简单的可以试试
    },
    delete(id) {
        // 删除数据库中的数据
        return userModel.deleteOne({ _id: id })
    },
    async deleteFile(src) {
        // 如果是默认数据 我把数据存储到public /images 中了其他的在uploads 中
        if (src.includes("/images")) return;
        // 因为删除文件没有文件会报错影响服务器 就try catch 处理一下
        try {
            return data = await fs.unlink(`./public/${src}`)

        } catch (error) {
            return false
        }

    }
}

module.exports = service

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK