国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

express框架中使用jwt實現(xiàn)驗證的方法

2019-11-19 10:58:40
字體:
供稿:網(wǎng)友

前言

接著上遍文章(使用session保存用戶數(shù)據(jù))來讓使用jwt保存用戶數(shù)據(jù)。

這里會用到passport-jwt/jsonwebtoken。

passport-jwt是passport的一個驗證策略。它使用jwt(json web token)驗證。

jsonwebtoken是一個編碼、解碼、驗證jwt的模塊。

使用jwt保存用戶數(shù)據(jù)與使用session保存用戶數(shù)據(jù)對比

session json web token
保存在server 保存在client

因session保存在server,所以服務器壓力比較大。聽說并發(fā)量達到1k時就能看到效果。

因jwt保存在client,所以需要加密。

使用jwt

1. 安裝依賴。

npm i passport-jwt jsonwebtoken

2. 創(chuàng)建一個配置文件,引用配置是使用。

// ./config.jsmodule.exports = { secretKey: '12345-67890-9876-54321', mongoUrl: 'mongodb://localhost:27017/confusion'}

3. 使用數(shù)據(jù)庫鏈接配置

var config = require('./config')...const url = config.mongoUrlconst connet = mongoose.connect(url, {useNewUrlParse: true, useCreateIndex: true})

4. 創(chuàng)建驗證文件

./authenticate.jsvar passport = require('passport'), LocalStrategy = require('passport-local').Strategy, User = require('./models/user')var JwtStrategy = require('passport-jwt').Strategy, ExtractJwt = require('passport-jwt').ExtractJwt, jwt = require('jsonwebtoken')var config = require('./config.js')passport.use(new LocalStrategy(User.authenticate()))passport.serializeUser(User.serializeUser())passport.deserializeUser(User.deserializeUser())exports.getToken = function (user) { return jwt.sign(user, config.secretKey, {expiresIn: 3600}) // 簽發(fā)token時設置超時時間是3600s}var opts = {}opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken() // 從驗證頭中提取,模型默認是`'bearer'`.opts.secretOrKey = config.secretKeyexports.jwtPassport = passport.use(new JwtStrategy(opts, (jwt_payload, done) => { console.log('JWT payload: ', jwt_payload) User.findOne({_id: jwt_payload._id}, (err, user) => { if (err) { return done(err, false) } else { if (user) { return done(null, user) } else { return done(null, false) } } })}))exports.verifyUser = passport.authenticate('jwt', {session: false}) // 使用jwt就不再需要session保存用戶數(shù)據(jù)了。

5. 用戶申請登錄時把jwt給前端

// routes/users.js...var authenticate = require('../authticate')router.post('/login', passport.authenticate('local'), (req, res) => { // 登錄時還是使用passport-local var token = authenticate.getToken({_id: req.user._id}) // 得到簽發(fā)后的jwt res.statusCode = 200 res.setHeader('Content-Type', 'application/json') res.json({success: true, token: token, status: 'You are successful logged in!'})})

6. 前端保存token

// use localStorage$.ajax({ type: 'post', dataType: 'json', url: 'users/login', data: { username: 'un', password: 'pw' }, success: funciton (res) { localStorage.token = getToken(res) }, error: funciton (err) {...}})// 還可以使用vux方法。// 還可以使用封裝axios方法。

7. 用戶登錄超時
jsonwebtoken驗證jwt后,若結果不通過,會有3種錯誤類型。分別是

TokenExpiredError // 當token超時時拋出。

err = { name: 'TokenExpiredError', massage: 'jwt expired', expired: [ExpDate]}JsonWebTokenError

jwt錯誤

err = { name: 'JsonWebTokenError', message: 'jwt malformed' // 'jwt malformed', 'jwt signature in required', 'invalid signature', 'jwt audience invalid. expected: [OPTIONS AUDIENCE]', 'jwt issuer invalid. expected: [OPTIONS ISSUER]', 'jwt id invalid. expected:[OPTIONS JWT ID]', 'jwt subject invalid. expected: [OPTIONS SUBJECT]'}

NotBeforeError

當當前時間超過nbf的值時拋出該錯誤。

err = { name: 'NotBeforeError', message: 'jwt not active', date: 2018-10-04T16:10:44.000Z}

passport在驗證jwt不通過時(token過期也是一種不通過)自動向前端發(fā)送“狀態(tài)碼為401,內(nèi)容是Unauthorized”.
在使用passport/passport-jwt/jsonwebtoken時沒有發(fā)現(xiàn)處理token過期的方法。所以在使用passport-jwt驗證不通過時再寫一個驗證是否過期的方法。

// authenicate.js...export.verifyUser = passport.authenticate('jwt', { session: false, failureRedirect: '/error/auth' // 在這個路由里統(tǒng)一處理驗證不通過的事情 })
// routes/error.js...router.get('/auth', (req, res, next) => { let header = req.headers let rawToken = header.authorization if (!rawToken.split(' ').length) { res.json({ // 統(tǒng)一的數(shù)據(jù)結構方便前端使用 code: 403, data: {}, message: 'error for get token' }) } else { let token = rawToken.split(' ')[1] jwt.verify(token, config.secretKey, err => { // 這里用到jsonwebtoken/config。注意引用 switch (err.name) { case 'TokenExpiredError': case 'NotBeforeError':  let payload = jwt.decode(token)  token = authenticate.getToken({_id: payload._id})  res.statusCode = 200  res.setHeader('Content-Type', 'application/json')  res.json({success: true, token: token, status: '已經(jīng)刷新token'})  break case 'JsonWebTokenError': default:  res.statusCode = 401  res.json({  code: 401,  data: {  error: err  },  message: 'token錯誤'  })  break } }) } })

8. 用戶jwt驗證不通過

passport在驗證jwt不通過時(token過期也是一種不通過)自動向前端發(fā)送“狀態(tài)碼為401,內(nèi)容是Unauthorized”.

9. 用戶申請登出

在前端刪除token.

10. 不要打斷活動用戶的操作

在no.7里若因為token過期造成驗證不通過,則向前端返回了新的token。不是在不影響用戶操作前提下更新用戶的token的。下面在的總結的幾種不影響用戶操作的前提下更新用戶的token的方法。

  1. 前端設置一個定時器。在小于過期時間時向后端請求新token并保存起來。
  2. 把token放在cookie時。后端從cookie里取出token,在過期前更新token。
  3. 將 token 存入 DB(如 Redis)中,失效則刪除;但增加了一個每次校驗時候都要先從 DB 中查詢 token 是否存在的步驟,而且違背了 JWT 的無狀態(tài)原則(這不就和 session 一樣了么?)。

總結

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對武林網(wǎng)的支持。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 昌都县| 冕宁县| 南召县| 安化县| 平昌县| 嘉峪关市| 武胜县| 九台市| 新乡市| 定南县| 漯河市| 大港区| 咸宁市| 禹州市| 林西县| 金沙县| 越西县| 乌鲁木齐县| 海阳市| 商南县| 奉新县| 三河市| 二连浩特市| 武义县| 陇西县| 西乌| 海口市| 确山县| 峡江县| 新蔡县| 时尚| 云南省| 紫金县| 宽甸| 翁牛特旗| 长武县| 宜章县| 子洲县| 大同县| 清涧县| 房山区|