說明:源碼已經所有上傳到github,倉庫地址: https://github.com/BM-laoli/Node-api-Designhtml
首先咱們的有一個app.js這個就是根路由起點,用來最初的打入口
它的功能有:
1.1 引入模塊建立基礎的網站服務器,
1.2 導入bodyPasser,過濾還有處理咱們的post請求
1.3 導入數據庫鏈接
1.4 把路由開放出去git
再來一個main.js它在個人route文件夾下,
2.1 什麼需啊喲再這裏作二次攔截,再進行分配路由,
2.2 引入兩個邏輯處理模塊,當請求發來的時候,若是不是login那麼咱們就須要驗證token,
2.3 若是訪問的是login那麼咱們須要,發post數據,來到處理驗證,而後拿token,
2.4 若是有token,那麼再來訪問2.2這裏的不是logi的其它路由路徑,的校驗就經過了,因而乎咱們就能分配各類接口了es6
詳細的講解輔助,工具代碼
3.1 這裏有咱們在主線邏輯裏須要的一些工具
3.2 中間件Middleware,裏面有兩個工具,一個是生成token的一個校驗token的
3.3 在3.2中的功能 須要依賴model下的一個util下的jwt工具生成token生成的依據是兩個密鑰對
3.4 咱們還有兩個工具,content 建立數據庫的連接,create初始化數據還有開發數據操做對象github
請求地址 | 請求方式 |
---|---|
/main/login | POST |
參數名稱 | 是否必選 | 參數說明 |
---|---|---|
是 | 郵箱 | |
password | 是 | 密碼 |
{ "status": 200, "msg": "登錄成功", "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiNWU5MTIwMTViOWI0NmYzZmE4Y2MzMjUzIiwiZXhwIjoxNTg2OTUyMzk1LCJpYXQiOjE1ODY5NTA1OTV9.IsprCaQ_gZRh0BzS8SnAd0iJ27BOpOEb-ZGn0bTlwHVPTiYPK50wiEOL_0aAYINfNT_Mfvb726l3CpiHG9lsJ45m4eqhPeJz9TbAeQj8-ST3CAkYLrD0fhgRG9YiQ5kjVpygdR8NZEWEUV7ux-moyYe7wCoVzN9mbvAkFF3IYG0" }
請求地址 | 請求方式 |
---|---|
/main/text | get |
參數名稱 | 是否必選 | 參數說明 |
---|---|---|
token | 是 | 須要附上你的token。在請求頭中 |
無 | 無 | 該接口不須要傳遞參數 |
{ "status": 200, "msg": "登錄成功" }
注意:以上就是Node寫接口的最基礎的內容。能夠在這個內容上擴展更多的接口web
app.jsmongodb
//引入模塊,建立簡單服務器 const express = require('express'); //引入路徑處理模塊 const path = require('path'); //引入注意使用第三方模塊處理post const bodyPaser = require('body-parser') // 引入數據庫鏈接 不須要返回值 require('./model/content') //建立服務器 const app = express(); /*//初始化數據庫,注意reque的時候 會自動執行引入的js文件 require('./model/create') */ //前往當心這個要放在全部的use前面,解析咱們的post請求數據 app.use(bodyPaser.urlencoded({ extended: false })); //處理靜態資源路徑 const DataPath = path.join(__dirname, 'public'); //這個咱們後面是有用的,用來操做媒體數據,最重要的就是這個路徑還有這個靜態資源對象 const StaticUtils = express.static(path.join(__dirname, 'public')); //拿到路由操做對象 const main = require('./route/mian/main'); //開放接口路徑 //攔截請求開始匹配路由 app.use('/dataPath', (req, res) => { res.status(200).send(JSON.stringify({ 'dataPath': DataPath })) }) app.use(StaticUtils); app.use('/main', main) //監聽端口 app.listen(3000) console.log('服務器開啓');
main.js數據庫
const express = require('express') //業務邏輯 const guard = require('../../Middleware/loginGuard') const loginPash = require('../../Middleware/loginPash') //建立路由對象 const admin = express.Router() //驗證token admin.use(loginPash) //登陸路由處理 admin.post('/login', guard) //首先要驗證,而後纔是放行到對應的路由接口裏面取 admin.get('/text', require('./API/home/index')) module.exports = admin;
module.exports = async(req, res) => { res.send({ status: 200, msg: '登錄成功', }); }
const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/blog') .then(() => { console.log('數據庫鏈接成功'); }) .catch((erro) => { console.log(erro); })
const mongoose = require('mongoose'); const bcrypt = require('bcrypt') /*使用MongDB數據庫,設計數據第一步(代碼角度分析) 1.設定規則,Schema構造器,Schema的構造函數就是規則,注意規則是一系列對象 2.建立數據 */ const userSchema = new mongoose.Schema({ username: { type: String, required: true, min: 2, max: 10 }, email: { type: String, //注意 咱們的郵箱憑據是用戶登陸的令牌,咱們須要指定他爲惟一的 unique: true, //這個時候,在插入的時候若是有重複的就給你抱一個錯誤 }, password: { type: String, required: true, }, role: { //須要說明一下,這個地方角色,咱們硬性規定,超級管理員是admin普通用戶是normal,爲何不用01?由於這裏string了 type: String, required: true }, state: { //咱們使用O1狀態來設計這個數據字段,默認值是0。0是啓用狀態 type: Number, default: 0 } }) //使用規則建立集合, //必定要注意,咱們的User就是表明了我目前最user數據集合,後期的增刪改查咱們都須要用到這個東西,全部咱們暴露出去給路由業務使用 const User = mongoose.model('User', userSchema) //咱們再來複習一下,如何用同步的方式獲取異步的api結果?使用async 還有awit就能夠 async function createUser() { const salt = await bcrypt.genSalt(10) const pass = await bcrypt.hash('123456', salt) const user = await User.create({ username: 'lli', email: '18376621755@163.com', password: pass, role: 'admin', state: 0, }) } // createUser() /* // 初始化用戶,注意咱們的create返回的是一個promies User.create({ username: 'bmlaoli', email: '861795660@qq.com', password: '123456', role: 'admin', state: 0, }) .then(() => { console.log('用戶建立成功'); }) .catch((error) => { console.log('用戶建立失敗'); })*/ //注意啊,es6中若是鍵值對的名字是同樣的就能夠省略值。因爲咱們後期還會作更多的數據集合,因而乎我這裏須要暴露一個對象出去 module.exports = { User }
/* *描述:如下是jwt工具,生成用於訪問驗證的token */ // 引入模塊依賴 const fs = require('fs'); const path = require('path'); const jwt = require('jsonwebtoken'); // 建立 token 類 class Jwt { constructor(data) { this.data = data; } //生成token generateToken() { let data = this.data; let created = Math.floor(Date.now() / 1000); let cert = fs.readFileSync(path.join(__dirname, '../../pem/private_key.pem')); //私鑰 能夠本身生成,注意這裏要使用 密鑰對,請求百度下載,兩對密鑰對 let token = jwt.sign({ data, exp: created + 60 * 30, }, cert, { algorithm: 'RS256' }); return token; } // 校驗token verifyToken() { let token = this.data; let cert = fs.readFileSync(path.join(__dirname, '../../pem/public_key.pem')); //公鑰 能夠本身生成 let res; try { let result = jwt.verify(token, cert, { algorithms: ['RS256'] }) || {}; let { exp = 0 } = result, current = Math.floor(Date.now() / 1000); if (current <= exp) { res = result.data || {}; } } catch (e) { res = 'err'; } return res; } } module.exports = Jwt;
const JwtUtil = require('../model/util/jwt') const { User } = require('../model/create') const bcrypt = require('bcrypt') const guard = async(req, res, next) => { //注意使用第三方模塊處理post //進圖具體的業務邏輯,解構出來咱們須要的東西 const { email, password, _id } = req.body; //注意啊,因爲咱們的中間件處理的請求因而乎咱們的req身上就有這個處理的全部數據了,這個以前有說過 console.log(req.body); if (email.trim().length == 0 || password.trim().length == 0) { res.status(400).send( JSON.stringify({ message: '郵箱或密碼錯誤' }) ) //注意send自動把狀態碼設置成了200,因此你須要改一下 return } //若是用戶存在就先找到這個用戶額信息,注意這裏的這個異步await let user = await User.findOne({ email }); //這裏的user就是指向當前查詢出來的數據文檔對象 if (user) { //比對操做,第一個參數是一個明文密碼,第二個參數咱們查詢出來的加密密碼 ,方法返回一個Boolean值,對比成功就是true,異步api能夠直接加await const isValid = await bcrypt.compare(password, user.password) if (isValid) { //用戶校驗成功,添加tooken // 登錄成功,添加token驗證 let _id = user._id.toString(); // 將用戶id傳入並生成token let jwt = new JwtUtil(_id); let token = jwt.generateToken(); // 將 token 返回給客戶端 res.send({ status: 200, msg: '登錄成功', token: token }); //校驗成功就 next() } else { res.status(400).send( JSON.stringify({ message: '郵箱或密碼錯誤' }) ) } } else { res.status(400).send( JSON.stringify({ message: '郵箱或密碼錯誤' }) ) } } module.exports = guard
loginPash.jsexpress
const JwtUtil = require('../model/util/jwt') //驗證token const loginPash = function(req, res, next) { // 我這裏知識把登錄和註冊請求去掉了,其餘的多有請求都須要進行token校驗 if (req.url != '/login?') { let token = req.headers.token; let jwt = new JwtUtil(token); let result = jwt.verifyToken(); // 若是考驗經過就next,不然就返回登錄信息不正確 if (result == 'err') { console.log(result); console.log(req.url); res.send({ status: 403, msg: '登陸已過時,請從新登陸' }); // res.render('login.html'); } else { next(); } } else { next(); } }; module.exports = loginPash;
其實這套接口下來,我比較菜雞,用了兩天的工做之餘的時間,因爲我沒怎麼接觸接口的設計,對於後臺的一些設計模式還有理念不是特別懂,走了不少彎路,以上的是我寫了三次筆記,長達2000多行子,反覆的修改,才成型,但願大佬高擡貴手指點迷津,也但願,這篇入門的文檔,能給你帶來收穫,接下里,我就用這裏的模型,開發更多的接口。敬請期待。json