node腳手架搭建伺服器實現token驗證的方法
內容
- 用腳手架快速搭建 node 專案
- 用 mysql 連線池實現與資料庫的互動
- 用 jsonwebtoken 實現 token 身份驗證
- 綜合案例:用簡介登入頁面實現上述內容
1. 快速搭建 node 專案
我們都知道 express 框架可高效的開發 node 伺服器,但對於底層的搭建還要靠自己手寫。然而 express-generator 的出現就很好地解決了此問題,它可一鍵為我們生成專案基本骨架,可謂node 腳手架
1.1 生成專案
①:首先全域性安裝 express : npm install express -g
②:接著全域性安裝 express-generator:npm install express-generator -g
1.2 修改入口檔案
對於好多習慣了手擼伺服器的人,app.js 總是讓人難忘,奈何此骨架中入口檔案為 www.js。此時我們可以手動修改app.js 程式碼,讓其成為我們的入口檔案
示例:
var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); const index = require('./routes/index'); const users = require('./routes/users'); const app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname,'public'))); app.use('/',index); app.use('/users',users); app.listen(3000,() => console.log('server is run 3000'))
2. 連線mysql 資料庫
此處採用連線池的方式進行連線(高效安全)
2.1 建立連線
①:安裝 mysql 模組:npm i mysql
②:在專案根目錄下配置連線池
首先在專案根目錄下建立 util 資料夾,資料夾下建立 bdconfig.js 檔案
bdconfig.js
const mysql = require('mysql'); module.exports = { mysqlParams: { host: 'localhost',//域名 port: '3306',//埠 user: 'root',//使用者名稱 password: 'myroot',//密碼 database: 'nodeapi' //資料庫 },sySqlConnect(sql,sqlArr) { return new Promise((resolve,reject) => { //用Promise物件將其改造,方便接收資料 const pool = mysql.createPool(this.mysqlParams); pool.getConnection((err,conn) => { if (err) { reject(err) } else { conn.query(sql,sqlArr,(err,data) => { //操作資料庫 if (err) { reject(err) } else { resolve(data) } }) conn.release() //釋放連線 } }) }) } }
2.2 使用連線
使用時只需要傳入 sql(sql語句)、sqlArr(引數),通過Promise 改造後可直接用返回值拿到結果
3. token 身份驗證
隨著web 的發展,session、cookie 的驗證方式弊端也愈發突出,此時token孕育而生,token的強大不僅限於其是無狀態的,還在於它可以跨域
3.1 實現步驟
①:首先安裝 jsonwebtoken 模組:npm i jsonwebtoken
②:接著在專案中使用該模組
const dbConfig = require('../util/dbconfig'); const jwt = require('jsonwebtoken'); const secret = 'login-rule'; //祕鑰規則(自定義) token = async(req,res,next) => { //定義token驗證中介軟體函式(應用於除登入外的每個請求) if (req.headers.authorization) { const token = req.headers.authorization; const { id,username } = jwt.verify(token,secret); // 對token進行解密查詢 let sql = 'select * from test where id=?'; let sqlArr = [id]; let result = await dbConfig.sySqlConnect(sql,sqlArr); if (result.length === 0) { res.status(200).send({ msg: '使用者錯誤' }) return } if (username !== result[0].username) { res.status(200).send({ msg: '使用者錯誤' }) } else { next() } } else { res.status(200).send({ msg: '無效請求頭' }) } } login = async(req,res) => { //定義登入介面(因為這個請求頭不攜帶token,所以引用在token驗證中介軟體之前) let { username,password } = req.body; let sql = 'select * from test where username=?'; let sqlArr = [username]; let result = await dbConfig.sySqlConnect(sql,sqlArr); if (result.length) { if (password === result[0].password) { const { id,username } = result[0]; //對token進行加密響應個客戶端(引數1:傳值規則;引數2:加密規則; 引數3:定義時間) const token = jwt.sign({ id,username },secret,{ expiresIn: 60 * 60 }); res.status(200).send({ msg: '登陸成功',token: token,status: 200 }); } else { res.status(200).send({ msg: '登陸失敗',status: 422 }); } } else { res.status(200).send({ msg: '使用者名稱不存在',status: 401 }) } } // 驗證身份中介軟體 module.exports = { token,login }
③:在 app.js 中進行配置
// 寫在 app.use() 之後,路由之前 app.use('/users/loginjwt',token.login); //登入介面(無需驗證token,所以寫在token中介軟體之前) app.use(token.token);
4. 案例實現 token
4.1 原理闡述
為確保身份唯一且有效:使用者每次傳送登入請求且登入成功,伺服器端都會響應給使用者一個含使用者資訊(唯一)的加密 token(字串),此時使用者接收到 token,並把 token 儲存在 sessionStorage 或 localStorage中(此處為)。同時使用者每次傳送其他請求時,在請求頭中攜帶本地的 token,伺服器端 token驗證中介軟體攔截請求,對 token進行解密,得到使用者資訊並與資料庫比對,資訊存在則放行(身份驗證成功)。
4.2 效果預覽
4.3 開始實現
寫簡潔靜態頁面,且實現ajax 請求
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <script src="../javascripts/jquery.min.js"></script> <title>Document</title> </head> <body> <form id="loginform"> <input type="text" name="username"> <input type="password" name="password"> <input type="submit" value="登入"> </form> <script> $(function() { $('#loginform').on('submit',function() { const formdata = $(this).serialize() $.ajax({ url: '/users/loginjwt',type: 'post',data: formdata,success(res) { if (res.status === 200) { window.sessionStorage.setItem('token',res.token); location.href = '/user/index.html' } } }) return false }) }) </script> </body> </html>
index.html
<script> if (!sessionStorage.getItem('token')) { location.href = '/user/login.html' } </script> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <script src="../javascripts/jquery.min.js"></script> <title>Document</title> </head> <body> <h1>welcome index</h1> <a href="javascript:;" rel="external nofollow" >退出登入</a> <script> $(function() { $.ajaxSetup({ // 傳送請求前觸發 beforeSend(xhr) { // 在此設定自定義請求頭 xhr.setRequestHeader('authorization',sessionStorage.getItem('token')) } }) $.ajax({ url: '/users',success(res) { console.log(res); } }) $('a').on('click',function() { sessionStorage.clear(); location.href = '/user/login.html' }) }) </script> </body> </html>
4.4 注意點
值得注意的是,對於 本地 token 的驗證(是否存在)一定要寫在頁面最頂端(防止頁面載入,再次傳送使用者列表請求)
對於 ajax請求頭,一個一個加真的很煩,此處用 $ajaxSetup方法,修改ajax 的預設配置 。配置過後,寫在其下邊的 ajax 請求,都會帶上請求頭。
到此這篇關於node腳手架搭建伺服器實現token驗證的方法的文章就介紹到這了,更多相關node token驗證 內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!