NODE 基于express 框架和mongoDB的cookie和session认证 和图片的上传和删除
源码地址
//gitee.com/zyqwasd/mongdbSession
本项目的mongodb是本地的mongodb 开启方法可以百度一下 端口是默认的27017
页面效果
1. 注册登录页
2. 上传的图片 和删除数据库的数据和服务器上的图片
前端代码 因为是个小项目就用原生写了
1. 这个是login 页面一个注册模块一个登录模块
<!-- 引入axios 方便操作 --> <script src="//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