自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Node.js 應(yīng)用:Koa2 使用 JWT 進(jìn)行鑒權(quán)

開發(fā) 開發(fā)工具
在前后端分離的開發(fā)中,通過 Restful API 進(jìn)行數(shù)據(jù)交互時(shí),如果沒有對(duì) API 進(jìn)行保護(hù),那么別人就可以很容易地獲取并調(diào)用這些 API 進(jìn)行操作。那么服務(wù)器端要如何進(jìn)行鑒權(quán)呢?

在前后端分離的開發(fā)中,通過 Restful API 進(jìn)行數(shù)據(jù)交互時(shí),如果沒有對(duì) API 進(jìn)行保護(hù),那么別人就可以很容易地獲取并調(diào)用這些 API 進(jìn)行操作。那么服務(wù)器端要如何進(jìn)行鑒權(quán)呢?

Json Web Token 簡(jiǎn)稱為 JWT,它定義了一種用于簡(jiǎn)潔、自包含的用于通信雙方之間以 JSON 對(duì)象的形式安全傳遞信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對(duì)進(jìn)行簽名。

說得好像跟真的一樣,那么到底要怎么進(jìn)行認(rèn)證呢?

首先用戶登錄時(shí),輸入用戶名和密碼后請(qǐng)求服務(wù)器登錄接口,服務(wù)器驗(yàn)證用戶名密碼正確后,生成token并返回給前端,前端存儲(chǔ)token,并在后面的請(qǐng)求中把token帶在請(qǐng)求頭中傳給服務(wù)器,服務(wù)器驗(yàn)證token有效,返回正確數(shù)據(jù)。

既然服務(wù)器端使用 Koa2 框架進(jìn)行開發(fā),除了要使用到 jsonwebtoken 庫(kù)之外,還要使用一個(gè) koa-jwt 中間件,該中間件針對(duì) Koa 對(duì) jsonwebtoken 進(jìn)行了封裝,使用起來更加方便。下面就來看看是如何使用的。

生成token

這里注冊(cè)了個(gè) /login 的路由,用于用戶登錄時(shí)獲取token。

  1. const router = require('koa-router')(); 
  2. const jwt = require('jsonwebtoken'); 
  3. const userModel = require('../models/userModel.js'); 
  4. router.post('/login', async (ctx) => { 
  5.     const data = ctx.request.body; 
  6.     if(!data.name || !data.password){ 
  7.         return ctx.body = { 
  8.             code: '000002'
  9.             data: null
  10.             msg: '參數(shù)不合法' 
  11.         } 
  12.     } 
  13.     const result = await userModel.findOne({ 
  14.         name: data.name
  15.         password: data.password 
  16.     }) 
  17.     if(result !== null){ 
  18.         const token = jwt.sign({ 
  19.             name: result.name
  20.             _id: result._id 
  21.         }, 'my_token', { expiresIn: '2h' }); 
  22.         return ctx.body = { 
  23.             code: '000001'
  24.             data: token, 
  25.             msg: '登錄成功' 
  26.         } 
  27.     }else
  28.         return ctx.body = { 
  29.             code: '000002'
  30.             data: null
  31.             msg: '用戶名或密碼錯(cuò)誤' 
  32.         } 
  33.     } 
  34. }); 
  35. module.exports = router; 

在驗(yàn)證了用戶名密碼正確之后,調(diào)用 jsonwebtoken 的 sign() 方法來生成token,接收三個(gè)參數(shù),第一個(gè)是載荷,用于編碼后存儲(chǔ)在 token 中的數(shù)據(jù),也是驗(yàn)證 token 后可以拿到的數(shù)據(jù);第二個(gè)是密鑰,自己定義的,驗(yàn)證的時(shí)候也是要相同的密鑰才能解碼;第三個(gè)是options,可以設(shè)置 token 的過期時(shí)間。

獲取token

接下來就是前端獲取 token,這里是在 vue.js 中使用 axios 進(jìn)行請(qǐng)求,請(qǐng)求成功之后拿到 token 保存到 localStorage 中。這里登錄成功后,還把當(dāng)前時(shí)間存了起來,除了判斷 token 是否存在之外,還可以再簡(jiǎn)單的判斷一下當(dāng)前 token 是否過期,如果過期,則跳登錄頁(yè)面

  1. submit(){ 
  2.     axios.post('/login', { 
  3.         name: this.username, 
  4.         password: this.password 
  5.     }).then(res => { 
  6.         if(res.code === '000001'){ 
  7.             localStorage.setItem('token', res.data); 
  8.             localStorage.setItem('token_exp', new Date().getTime()); 
  9.             this.$router.push('/'); 
  10.         }else
  11.             alert(res.msg); 
  12.         } 
  13.     }) 

然后請(qǐng)求服務(wù)器端API的時(shí)候,把 token 帶在請(qǐng)求頭中傳給服務(wù)器進(jìn)行驗(yàn)證。每次請(qǐng)求都要獲取 localStorage 中的 token,這樣很麻煩,這里使用了 axios 的請(qǐng)求攔截器,對(duì)每次請(qǐng)求都進(jìn)行了取 token 放到 headers 中的操作。

  1. axios.interceptors.request.use(config => { 
  2.     const token = localStorage.getItem('token'); 
  3.     config.headers.common['Authorization'] = 'Bearer ' + token; 
  4.     return config; 
  5. }) 

驗(yàn)證token

通過 koa-jwt 中間件來進(jìn)行驗(yàn)證,用法也非常簡(jiǎn)單

  1. const koa = require('koa'); 
  2. const koajwt = require('koa-jwt'); 
  3. const app = new koa(); 
  4. // 錯(cuò)誤處理 
  5. app.use((ctx, next) => { 
  6.     return next().catch((err) => { 
  7.         if(err.status === 401){ 
  8.             ctx.status = 401; 
  9.             ctx.body = 'Protected resource, use Authorization header to get access\n'
  10.         }else
  11.             throw err; 
  12.         } 
  13.     }) 
  14. }) 
  15. app.use(koajwt({ 
  16.     secret: 'my_token' 
  17. }).unless({ 
  18.     path: [/\/user\/login/] 
  19. })); 

通過 app.use 來調(diào)用該中間件,并傳入密鑰 {secret: 'my_token'},unless 可以指定哪些 URL 不需要進(jìn)行 token 驗(yàn)證。token 驗(yàn)證失敗的時(shí)候會(huì)拋出401錯(cuò)誤,因此需要添加錯(cuò)誤處理,而且要放在 app.use(koajwt()) 之前,否則不執(zhí)行。

如果請(qǐng)求時(shí)沒有token或者token過期,則會(huì)返回401。

解析koa-jwt

我們上面使用 jsonwebtoken 的 sign() 方法來生成 token 的,那么 koa-jwt 做了些什么幫我們來驗(yàn)證 token。

resolvers/auth-header.js

  1. module.exports = function resolveAuthorizationHeader(ctx, opts) { 
  2.     if (!ctx.header || !ctx.header.authorization) { 
  3.         return
  4.     } 
  5.     const parts = ctx.header.authorization.split(' '); 
  6.     if (parts.length === 2) { 
  7.         const scheme = parts[0]; 
  8.         const credentials = parts[1]; 
  9.         if (/^Bearer$/i.test(scheme)) { 
  10.             return credentials; 
  11.         } 
  12.     } 
  13.     if (!opts.passthrough) { 
  14.         ctx.throw(401, 'Bad Authorization header format. Format is "Authorization: Bearer <token>"'); 
  15.     } 
  16. }; 

在 auth-header.js 中,判斷請(qǐng)求頭中是否帶了 authorization,如果有,將 token 從 authorization 中分離出來。如果沒有 authorization,則代表了客戶端沒有傳 token 到服務(wù)器,這時(shí)候就拋出 401 錯(cuò)誤狀態(tài)。

verify.js

  1. const jwt = require('jsonwebtoken'); 
  2. module.exports = (...args) => { 
  3.     return new Promise((resolve, reject) => { 
  4.         jwt.verify(...args, (error, decoded) => { 
  5.             error ? reject(error) : resolve(decoded); 
  6.         }); 
  7.     }); 
  8. }; 

在 verify.js 中,使用 jsonwebtoken 提供的 verify() 方法進(jìn)行驗(yàn)證返回結(jié)果。jsonwebtoken 的 sign() 方法來生成 token 的,而 verify() 方法則是用來認(rèn)證和解析 token。如果 token 無效,則會(huì)在此方法被驗(yàn)證出來。

index.js

  1. const decodedToken = await verify(token, secret, opts); 
  2. if (isRevoked) { 
  3.     const tokenRevoked = await isRevoked(ctx, decodedToken, token); 
  4.     if (tokenRevoked) { 
  5.         throw new Error('Token revoked'); 
  6.     } 
  7. ctx.state[key] = decodedToken;  // 這里的key = 'user' 
  8. if (tokenKey) { 
  9.     ctx.state[tokenKey] = token; 

在 index.js 中,調(diào)用 verify.js 的方法進(jìn)行驗(yàn)證并解析 token,拿到上面進(jìn)行 sign() 的數(shù)據(jù) {name: result.name, _id: result._id},并賦值給 ctx.state.user,在控制器中便可以直接通過 ctx.state.user 拿到 name 和 _id。

安全性

如果 JWT 的加密密鑰泄露的話,那么就可以通過密鑰生成 token,隨意的請(qǐng)求 API 了。因此密鑰絕對(duì)不能存在前端代碼中,不然很容易就能被找到。

在 HTTP 請(qǐng)求中,token 放在 header 中,中間者很容易可以通過抓包工具抓取到 header 里的數(shù)據(jù)。而 HTTPS 即使能被抓包,但是它是加密傳輸?shù)?,所以也拿不?token,就會(huì)相對(duì)安全了。

總結(jié)

這上面就是 jwt 基本的流程,這或許不是最完美的,但在大多數(shù)登錄中使用已經(jīng)足夠了。

上面的代碼可能不夠具體,這里使用 Koa + mongoose + vue.js 實(shí)現(xiàn)的一個(gè)例子 : jwt-demo,可以做為參考。

【本文為51CTO專欄作者“林鑫”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過微信公眾號(hào)聯(lián)系作者獲取授權(quán)】

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2016-08-25 21:28:04

前端node截圖

2021-06-15 15:03:21

MongoDBNode.jsCRUD

2013-03-28 14:54:36

2016-09-18 16:04:24

HTTPNode應(yīng)用

2017-04-18 09:27:14

Visual StudNode.js調(diào)試

2018-04-20 16:15:42

Koa2上傳下載

2022-08-28 16:30:34

Node.jsDocker指令

2023-01-10 14:11:26

2013-11-01 09:34:56

Node.js技術(shù)

2015-03-10 10:59:18

Node.js開發(fā)指南基礎(chǔ)介紹

2019-07-24 09:28:36

Node.jskoa架構(gòu)

2011-07-26 11:07:08

JavaScript

2019-05-05 11:47:09

TypeScript開發(fā)Node.js

2020-09-04 15:06:04

Docker容器化Node.js

2017-05-10 09:40:57

Ubuntupm2Nginx

2017-06-20 15:39:58

Koa2 應(yīng)用動(dòng)態(tài)Swagger文檔

2022-12-14 14:40:27

Node.js開發(fā)應(yīng)用程序

2021-03-03 06:39:05

Nodejs前端開發(fā)

2021-07-16 04:56:03

NodejsAddon

2012-09-29 11:13:15

Node.JS前端開發(fā)Node.js打包
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)