本文致力於用最簡單、最少的代碼完成用express實現加密(MD5)JWT功能,用於登陸驗證。javascript
JWT(json web token)是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準。(json格式傳token) JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源。好比用在用戶登陸上。前端
JWT的三個部分:JWT頭、有效載荷和簽名。java
JWT頭部分是一個描述JWT元數據的JSON對象,一般以下所示。ios
{web
「alg」: 「HS256」,算法
「typ」: 「JWT」express
} 上面代碼中,alg屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);typ屬性表示這個令牌(token)的類型(type),JWT 令牌統一寫爲JWT。json
Payload 部分也是一個 JSON 對象,用來存放實際須要傳遞的數據。JWT 規定了7個官方字段,供選用。axios
iss (issuer):簽發人 exp (expiration time):過時時間 sub (subject):主題 aud (audience):受衆 nbf (Not Before):生效時間 iat (Issued At):簽發時間 jti (JWT ID):編號 除此以外,你還能夠自定義字段,如:api
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
複製代碼
Signature 部分是對前兩部分的簽名,防止數據篡改。
首先,須要指定一個密鑰(secret)。這個密鑰只有服務器才知道,不能泄露給用戶。而後,使用 Header 裏面指定的簽名算法(默認是 HMAC SHA256),按照下面的公式產生簽名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
複製代碼
算出簽名之後,把 Header、Payload、Signature 三個部分拼成一個字符串,每一個部分之間用"點"(.)分隔,就能夠返回給用戶。
工做過程: 1.前端向服務端發送用戶名和密碼。
2.服務端生成JWT。
3.將生成的JWT發送到前端,相關數據(如用戶角色,登陸時間等)將保存在當前會話中。
4.前端向服務端請求數據時,將JWT放到Header中,發送給服務端。
5.服務端收到JWT,進行驗證,確認用戶信息。
6.驗證成功,返回數據給前端。
一、下載express-jwt (生成 token)+ jsonwebtoken(驗證 token)兩個包 二、設置了密碼鹽值以及token的secretKey(JWT默認是不加密的,這裏用到了MD5加密,並用salt對密碼進行了複雜化)
// /constant.js
var crypto = require('crypto');
module.exports = {
MD5_SUFFIX: 'houyuping', //固定長度的鹽值salt
md5: function (pwd) {
var md5 = crypto.createHash('md5');
return md5.update(pwd).digest('hex');
},
secretKey: 'yichen_qingting_jwttoken'
};
複製代碼
三、在登陸環節生成token
// /routes/user.js
var token = jwt.sign(data, constant.secretKey, {
expiresIn: 60 * 60 * 24 // 受權時效24小時
})
res.json({
success: true,
message: 'success',
token: token
})
複製代碼
四、設置攔截token的中間件,包括token的驗證以及錯誤信息的返回:
// /jwt.js
const expressJwt = require("express-jwt");
const secretKey = require('./constant');
// express-jwt中間件幫咱們自動作了token的驗證以及錯誤處理,因此通常狀況下咱們按照格式書寫就沒問題,其中unless放的就是你想要不檢驗token的api。
const jwtAuth = expressJwt({secret: secretKey.secretKey}).unless({path: ["/users/login","/users/query"]});
module.exports = jwtAuth;
複製代碼
五、最後在路由中間件前面放上jwt中間件
var express = require('express');
var router = express.Router();
var jwtAuth = require('./jwt')
// 全部請求過來都會進行身份驗證
router.use(jwtAuth);
// 路由中間件
router.use(function (req, res, next) {
// 任何路由信息都會執行這裏面的語句
console.log('this is a api request!');
// 把它交給下一個中間件,注意中間件的註冊順序是按序執行
next();
});
複製代碼
前端部分 一、將獲取的token保存到localstorage中
let token = window.localStorage.getItem("wyg_token");
複製代碼
二、每次請求帶上token,將token放入header中
this.$axios.post('http://127.0.0.1:3000/users/modifyPwd',
{data: data},
{headers: {'Authorization': `Bearer ${token}`}}
)
複製代碼
優勢:
缺點: