NODE 基於express 框架和mongoDB的cookie和session認證 和圖片的上傳和刪除
原始碼地址
http://gitee.com/zyqwasd/mongdbSession
本專案的mongodb是本地的mongodb 開啟方法可以百度一下 埠是預設的27017
頁面效果
1. 註冊登入頁
2. 上傳的圖片 和刪除資料庫的資料和伺服器上的圖片
前端程式碼 因為是個小專案就用原生寫了
1. 這個是login 頁面一個註冊模組一個登入模組
<!-- 引入axios 方便操作 --> <script src="http://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
「其他文章」
- 記一次批量更新整型型別的列 → 探究 UPDATE 的使用細節
- 編碼中的Adapter,不僅是一種設計模式,更是一種架構理念與解決方案
- 執行緒池底層原理詳解與原始碼分析
- 30分鐘掌握 Webpack
- 線性迴歸大結局(嶺(Ridge)、 Lasso迴歸原理、公式推導),你想要的這裡都有
- Django 之路由層
- 【前端必會】webpack loader 到底是什麼
- day42-反射01
- 中心化決議管理——雲端分析
- HashMap底層原理及jdk1.8原始碼解讀
- 詳解JS中 call 方法的實現
- 列印 Logger 日誌時,需不需要再封裝一下工具類?
- 初識設計模式 - 代理模式
- 設計模式---享元模式
- 密碼學奇妙之旅、01 CFB密文反饋模式、AES標準、Golang程式碼
- [ML從入門到入門] 支援向量機:從SVM的推導過程到SMO的收斂性討論
- 從應用訪問Pod元資料-DownwardApi的應用
- Springboot之 Mybatis 多資料來源實現
- Java 泛型程式設計
- CAS核心思想、底層實現