中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

express框架中使用jwt實現驗證的方法

發布時間:2020-08-30 13:33:29 來源:腳本之家 閱讀:300 作者:飛機 欄目:web開發

前言

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

這里會用到passport-jwt/jsonwebtoken。

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

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

使用jwt保存用戶數據與使用session保存用戶數據對比

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

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

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

使用jwt

1. 安裝依賴。

npm i passport-jwt jsonwebtoken

2. 創建一個配置文件,引用配置是使用。

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

3. 使用數據庫鏈接配置

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

4. 創建驗證文件

./authenticate.js
var 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}) // 簽發token時設置超時時間是3600s
}

var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken() // 從驗證頭中提取,模型默認是`'bearer'`.
opts.secretOrKey = config.secretKey

exports.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保存用戶數據了。

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}) // 得到簽發后的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過期也是一種不通過)自動向前端發送“狀態碼為401,內容是Unauthorized”.
在使用passport/passport-jwt/jsonwebtoken時沒有發現處理token過期的方法。所以在使用passport-jwt驗證不通過時再寫一個驗證是否過期的方法。

// authenicate.js
...
export.verifyUser = passport.authenticate('jwt', {
 session: false,
 failureRedirect: '/error/auth' // 在這個路由里統一處理驗證不通過的事情
 })
// routes/error.js
...
router.get('/auth', (req, res, next) => {
 let header = req.headers
 let rawToken = header.authorization
 if (!rawToken.split(' ').length) {
 res.json({ // 統一的數據結構方便前端使用
 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: '已經刷新token'})
  break
 case 'JsonWebTokenError':
 default:
  res.statusCode = 401
  res.json({
  code: 401,
  data: {
  error: err
  },
  message: 'token錯誤'
  })
  break
 }
 })
 }
 })

8. 用戶jwt驗證不通過

passport在驗證jwt不通過時(token過期也是一種不通過)自動向前端發送“狀態碼為401,內容是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 的無狀態原則(這不就和 session 一樣了么?)。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汝南县| 稷山县| 宕昌县| 扬中市| 墨江| 邓州市| 庆阳市| 丽水市| 福贡县| 安新县| 岑溪市| 台江县| 仲巴县| 阿巴嘎旗| 晋江市| 丰城市| 沐川县| 洛浦县| 江华| 吴桥县| 瓮安县| 璧山县| 无棣县| 九江市| 家居| 礼泉县| 罗源县| 房山区| 乐昌市| 大化| 清丰县| 图木舒克市| 澄迈县| 凤山县| 喀喇| 滁州市| 晋城| 商水县| 阳春市| 洛川县| 喀什市|