定制開發(fā)app到底要多少錢百度搜索引擎優(yōu)化指南最新版
目錄
- 1 Node 操作 mysql
- 1.2 操作 mysql 數據庫
- 2 Web 開發(fā)模式
- 2.1 服務端渲染
- 2.2 前后端分離
- 2.3 如何選擇
- 3 身份認證
- 3.1 Session 認證機制
- 3.2 JWT 認證機制
1 Node 操作 mysql
數據庫和身份認證
配置 mysql 模塊
- 安裝 mysql 模塊
npm install mysql
- 建立連接
const mysql = require('mysql')const db = mysql.createPool({host: '127.0.0.1',user: 'root',password: 'root',database: 'test',
})
- 測試是否正常工作
db.query('select 1', (err, results) => {if (err) return console.log(err.message)console.log(results)
})
1.2 操作 mysql 數據庫
- 查詢數據
db.query('select * from users', (err, results) => {...
})
- 插入數據
// ? 表示占位符
const sql = 'insert into users values(?, ?)'
// 使用數組的形式為占位符指定具體的值
db.query(sql, [username, password], (err, results) => {if (err) return console.log(err.message)if (results.affectedRows === 1) console.log('插入成功')
})
向表中新增數據時,如果數據對象的每個屬性和數據表的字段一一對應,則可以通過如下方式快速插入數據:
const user = {username:'Bruce', password:'55520'}
const sql = 'insert into users set ?'
db.query(sql, user, (err, results) => {...
})
- 更新數據
const sql = 'update users set username=?, password=? where id=?'
db.query(sql, [username, password, id], (err, results) => {...
})
快捷方式:
const user = {id:7,username:'Bruce',password:'55520'}
const sql = 'update users set ? where id=?'
db.query(sql, [user, user.id], (err, results) => {...
})
- 刪除數據
const sql = 'delete from users where id=?'
db.query(sql, id, (err, results) => {...
})
使用 delete 語句會真正刪除數據,保險起見,使用標記刪除的形式,模擬刪除的動作。即在表中設置狀態(tài)字段,標記當前的數據是否被刪除。
db.query('update users set status=1 where id=?', 7, (err, results) => {...
})
2 Web 開發(fā)模式
2.1 服務端渲染
服務器發(fā)送給客戶端的 HTML 頁面,是在服務器通過字符串的拼接動態(tài)生成的。因此客戶端不需要使用 Ajax 額外請求頁面的數據。
app.get('/index.html', (req, res) => {const user = { name: 'Bruce', age: 29 }const html = `<h1>username:${user.name}, age:${user.age}</h1>`res.send(html)
})
優(yōu)點:
- 前端耗時短。瀏覽器只需直接渲染頁面,無需額外請求數據。
- 有利于 SEO。服務器響應的是完整的 HTML 頁面內容,有利于爬蟲爬取信息。
缺點:
- 占用服務器資源。服務器需要完成頁面內容的拼接,若請求比較多,會對服務器造成一定訪問壓力。
- 不利于前后端分離,開發(fā)效率低。
2.2 前后端分離
前后端分離的開發(fā)模式,依賴于 Ajax 技術的廣泛應用。后端只負責提供 API 接口,前端使用 Ajax 調用接口。
優(yōu)點:
- 開發(fā)體驗好。前端專業(yè)頁面開發(fā),后端專注接口開發(fā)。
- 用戶體驗好。頁面局部刷新,無需重新請求頁面。
- 減輕服務器的渲染壓力。頁面最終在瀏覽器里生成。
缺點:
- 不利于 SEO。完整的 HTML 頁面在瀏覽器拼接完成,因此爬蟲無法爬取頁面的有效信息。Vue、React 等框架的 SSR(server side render)技術能解決 SEO 問題。
2.3 如何選擇
- 企業(yè)級網站,主要功能是展示,沒有復雜交互,且需要良好的 SEO,可考慮服務端渲染
- 后臺管理項目,交互性強,無需考慮 SEO,可使用前后端分離
- 為同時兼顧首頁渲染速度和前后端分離開發(fā)效率,可采用首屏服務器端渲染+其他頁面前后端分離的開發(fā)模式
3 身份認證
3.1 Session 認證機制
服務端渲染推薦使用 Session 認證機制
Session 工作原理
Express 中使用 Session 認證
- 安裝 express-session 中間件
npm install express-session
- 配置中間件
const session = require('express-session')
app.use(session({secret: 'Bruce', // secret 的值為任意字符串resave: false,saveUninitalized: true,})
)
- 向 session 中存數據
中間件配置成功后,可通過 req.session
訪問 session 對象,存儲用戶信息
app.post('/api/login', (req, res) => {req.session.user = req.bodyreq.session.isLogin = trueres.send({ status: 0, msg: 'login done' })
})
- 從 session 取數據
app.get('/api/username', (req, res) => {if (!req.session.isLogin) {return res.send({ status: 1, msg: 'fail' })}res.send({ status: 0, msg: 'success', username: req.session.user.username })
})
- 清空 session
app.post('/api/logout', (req, res) => {// 清空當前客戶端的session信息req.session.destroy()res.send({ status: 0, msg: 'logout done' })
})
3.2 JWT 認證機制
前后端分離推薦使用 JWT(JSON Web Token)認證機制,是目前最流行的跨域認證解決方案
JWT 工作原理
Session 認證的局限性:
- Session 認證機制需要配合 Cookie 才能實現。由于 Cookie 默認不支持跨域訪問,所以,當涉及到前端跨域請求后端接口的時候,需要做很多額外的配置,才能實現跨域 Session 認證。
- 當前端請求后端接口不存在跨域問題的時候,推薦使用 Session 身份認證機制。
- 當前端需要跨域請求后端接口的時候,不推薦使用 Session 身份認證機制,推薦使用 JWT 認證機制
JWT 工作原理圖:
用戶的信息通過 Token 字符串的形式,保存在客戶端瀏覽器中。服務器通過還原 Token 字符串的形式來認證用戶的身份。
JWT 組成部分:
- Header、Payload、Signature
- Payload 是真正的用戶信息,加密后的字符串
- Header 和 Signature 是安全性相關部分,保證 Token 安全性
- 三者使用
.
分隔
Header.Payload.SignatureeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTcsInVzZXJuYW1lIjoiQnJ1Y2UiLCJwYXNzd29yZCI6IiIsIm5pY2tuYW1lIjoiaGVsbG8iLCJlbWFpbCI6InNjdXRAcXEuY29tIiwidXNlcl9waWMiOiIiLCJpYXQiOjE2NDE4NjU3MzEsImV4cCI6MTY0MTkwMTczMX0.bmqzAkNSZgD8IZxRGGyVlVwGl7EGMtWitvjGD-a5U5c
JWT 使用方式:
- 客戶端會把 JWT 存儲在 localStorage 或 sessionStorage 中
- 此后客戶端與服務端通信需要攜帶 JWT 進行身份認證,將 JWT 存在 HTTP 請求頭 Authorization 字段中
- 加上 Bearer 前綴
Authorization: Bearer <token>
Express 使用 JWT
- 安裝
- jsonwebtoken 用于生成 JWT 字符串
- express-jwt 用于將 JWT 字符串解析還原成 JSON 對象
npm install jsonwebtoken express-jwt
- 定義 secret 密鑰
- 為保證 JWT 字符串的安全性,防止其在網絡傳輸過程中被破解,需定義用于加密和解密的 secret 密鑰
- 生成 JWT 字符串時,使用密鑰加密信息,得到加密好的 JWT 字符串
- 把 JWT 字符串解析還原成 JSON 對象時,使用密鑰解密
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')// 密鑰為任意字符串
const secretKey = 'Bruce'
- 生成 JWT 字符串
app.post('/api/login', (req, res) => {...res.send({status: 200,message: '登錄成功',// jwt.sign() 生成 JWT 字符串// 參數:用戶信息對象、加密密鑰、配置對象-token有效期// 盡量不保存敏感信息,因此只有用戶名,沒有密碼token: jwt.sign({username: userInfo.username}, secretKey, {expiresIn: '10h'})})
})
- JWT 字符串還原為 JSON 對象
- 客戶端訪問有權限的接口時,需通過請求頭的
Authorization
字段,將 Token 字符串發(fā)送到服務器進行身份認證 - 服務器可以通過 express-jwt 中間件將客戶端發(fā)送過來的 Token 解析還原成 JSON 對象
// unless({ path: [/^\/api\//] }) 指定哪些接口無需訪問權限
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))
- 獲取用戶信息
- 當 express-jwt 中間件配置成功后,即可在那些有權限的接口中,使用
req.user
對象,來訪問從 JWT 字符串中解析出來的用戶信息
app.get('/admin/getinfo', (req, res) => {console.log(req.user)res.send({status: 200,message: '獲取信息成功',data: req.user,})
})
- 捕獲解析 JWT 失敗后產生的錯誤
- 當使用 express-jwt 解析 Token 字符串時,如果客戶端發(fā)送過來的 Token 字符串過期或不合法,會產生一個解析失敗的錯誤,影響項目的正常運行
- 通過 Express 的錯誤中間件,捕獲這個錯誤并進行相關的處理
app.use((err, req, res, next) => {if (err.name === 'UnauthorizedError') {return res.send({ status: 401, message: 'Invalid token' })}res.send({ status: 500, message: 'Unknown error' })
})