您好,登錄后才能下訂單哦!
這篇文章給大家介紹使用node腳手架如何搭建一個(gè)服務(wù)器,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
我們都知道 express 框架可高效的開(kāi)發(fā) node 服務(wù)器,但對(duì)于底層的搭建還要靠自己手寫(xiě)。然而 express-generator 的出現(xiàn)就很好地解決了此問(wèn)題,它可一鍵為我們生成項(xiàng)目基本骨架,可謂node 腳手架
①:首先全局安裝 express : npm install express -g
②:接著全局安裝 express-generator:npm install express-generator -g
③:然后使用命令創(chuàng)建項(xiàng)目: express token_learn(項(xiàng)目名稱)
對(duì)于好多習(xí)慣了手?jǐn)]服務(wù)器的人,app.js 總是讓人難忘,奈何此骨架中入口文件為 www.js。此時(shí)我們可以手動(dòng)修改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'))
此處采用連接池的方式進(jìn)行連接(高效安全)
①:安裝 mysql 模塊:npm i mysql
②:在項(xiàng)目根目錄下配置連接池
首先在項(xiàng)目根目錄下創(chuàng)建 util 文件夾,文件夾下創(chuàng)建 bdconfig.js 文件
bdconfig.js
const mysql = require('mysql'); module.exports = { mysqlParams: { host: 'localhost', //域名 port: '3306', //端口 user: 'root', //用戶名 password: 'myroot', //密碼 database: 'nodeapi' //數(shù)據(jù)庫(kù) }, sySqlConnect(sql, sqlArr) { return new Promise((resolve, reject) => { //用Promise對(duì)象將其改造,方便接收數(shù)據(jù) const pool = mysql.createPool(this.mysqlParams); pool.getConnection((err, conn) => { if (err) { reject(err) } else { conn.query(sql, sqlArr, (err, data) => { //操作數(shù)據(jù)庫(kù) if (err) { reject(err) } else { resolve(data) } }) conn.release() //釋放連接 } }) }) } }
使用時(shí)只需要傳入 sql(sql語(yǔ)句)、sqlArr(參數(shù)),通過(guò)Promise 改造后可直接用返回值拿到結(jié)果
隨著web 的發(fā)展,session、cookie 的驗(yàn)證方式弊端也愈發(fā)突出,此時(shí)token孕育而生,token的強(qiáng)大不僅限于其是無(wú)狀態(tài)的,還在于它可以跨域
①:首先安裝 jsonwebtoken 模塊:npm i jsonwebtoken
②:接著在項(xiàng)目中使用該模塊
const dbConfig = require('../util/dbconfig'); const jwt = require('jsonwebtoken'); const secret = 'login-rule'; //秘鑰規(guī)則(自定義) token = async(req, res, next) => { //定義token驗(yàn)證中間件函數(shù)(應(yīng)用于除登錄外的每個(gè)請(qǐng)求) if (req.headers.authorization) { const token = req.headers.authorization; const { id, username } = jwt.verify(token, secret); // 對(duì)token進(jìn)行解密查找 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: '用戶錯(cuò)誤' }) return } if (username !== result[0].username) { res.status(200).send({ msg: '用戶錯(cuò)誤' }) } else { next() } } else { res.status(200).send({ msg: '無(wú)效請(qǐng)求頭' }) } } login = async(req, res) => { //定義登錄接口(因?yàn)檫@個(gè)請(qǐng)求頭不攜帶token,所以引用在token驗(yàn)證中間件之前) 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]; //對(duì)token進(jìn)行加密響應(yīng)個(gè)客戶端(參數(shù)1:傳值規(guī)則;參數(shù)2:加密規(guī)則; 參數(shù)3:定義時(shí)間) 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 }) } } // 驗(yàn)證身份中間件 module.exports = { token, login }
③:在 app.js 中進(jìn)行配置
// 寫(xiě)在 app.use() 之后,路由之前 app.use('/users/loginjwt', token.login); //登錄接口(無(wú)需驗(yàn)證token,所以寫(xiě)在token中間件之前) app.use(token.token);
為確保身份唯一且有效:用戶每次發(fā)送登錄請(qǐng)求且登錄成功,服務(wù)器端都會(huì)響應(yīng)給用戶一個(gè)含用戶信息(唯一)的加密 token(字符串),此時(shí)用戶接收到 token,并把 token 存儲(chǔ)在 sessionStorage 或 localStorage中(此處為)。同時(shí)用戶每次發(fā)送其他請(qǐng)求時(shí),在請(qǐng)求頭中攜帶本地的 token,服務(wù)器端 token驗(yàn)證中間件攔截請(qǐng)求,對(duì) token進(jìn)行解密,得到用戶信息并與數(shù)據(jù)庫(kù)比對(duì),信息存在則放行(身份驗(yàn)證成功)。
寫(xiě)簡(jiǎn)潔靜態(tài)頁(yè)面,且實(shí)現(xiàn)ajax 請(qǐng)求
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> <h2>welcome index</h2> <a href="javascript:;" rel="external nofollow" >退出登錄</a> <script> $(function() { $.ajaxSetup({ // 發(fā)送請(qǐng)求前觸發(fā) beforeSend(xhr) { // 在此設(shè)置自定義請(qǐng)求頭 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>
值得注意的是,對(duì)于 本地 token 的驗(yàn)證(是否存在)一定要寫(xiě)在頁(yè)面最頂端(防止頁(yè)面加載,再次發(fā)送用戶列表請(qǐng)求)
對(duì)于 ajax請(qǐng)求頭,一個(gè)一個(gè)加真的很煩,此處用 $ajaxSetup方法,修改ajax 的默認(rèn)配置 。配置過(guò)后,寫(xiě)在其下邊的 ajax 請(qǐng)求,都會(huì)帶上請(qǐng)求頭。
關(guān)于使用node腳手架如何搭建一個(gè)服務(wù)器就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。