成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Node.js 應用:Koa2 使用 JWT 進行鑒權

開發 開發工具
在前后端分離的開發中,通過 Restful API 進行數據交互時,如果沒有對 API 進行保護,那么別人就可以很容易地獲取并調用這些 API 進行操作。那么服務器端要如何進行鑒權呢?

在前后端分離的開發中,通過 Restful API 進行數據交互時,如果沒有對 API 進行保護,那么別人就可以很容易地獲取并調用這些 API 進行操作。那么服務器端要如何進行鑒權呢?

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

說得好像跟真的一樣,那么到底要怎么進行認證呢?

首先用戶登錄時,輸入用戶名和密碼后請求服務器登錄接口,服務器驗證用戶名密碼正確后,生成token并返回給前端,前端存儲token,并在后面的請求中把token帶在請求頭中傳給服務器,服務器驗證token有效,返回正確數據。

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

生成token

這里注冊了個 /login 的路由,用于用戶登錄時獲取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: '參數不合法' 
  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: '用戶名或密碼錯誤' 
  32.         } 
  33.     } 
  34. }); 
  35. module.exports = router; 

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

獲取token

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

  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.     }) 

然后請求服務器端API的時候,把 token 帶在請求頭中傳給服務器進行驗證。每次請求都要獲取 localStorage 中的 token,這樣很麻煩,這里使用了 axios 的請求攔截器,對每次請求都進行了取 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. }) 

驗證token

通過 koa-jwt 中間件來進行驗證,用法也非常簡單

  1. const koa = require('koa'); 
  2. const koajwt = require('koa-jwt'); 
  3. const app = new koa(); 
  4. // 錯誤處理 
  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 來調用該中間件,并傳入密鑰 {secret: 'my_token'},unless 可以指定哪些 URL 不需要進行 token 驗證。token 驗證失敗的時候會拋出401錯誤,因此需要添加錯誤處理,而且要放在 app.use(koajwt()) 之前,否則不執行。

如果請求時沒有token或者token過期,則會返回401。

解析koa-jwt

我們上面使用 jsonwebtoken 的 sign() 方法來生成 token 的,那么 koa-jwt 做了些什么幫我們來驗證 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 中,判斷請求頭中是否帶了 authorization,如果有,將 token 從 authorization 中分離出來。如果沒有 authorization,則代表了客戶端沒有傳 token 到服務器,這時候就拋出 401 錯誤狀態。

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() 方法進行驗證返回結果。jsonwebtoken 的 sign() 方法來生成 token 的,而 verify() 方法則是用來認證和解析 token。如果 token 無效,則會在此方法被驗證出來。

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 中,調用 verify.js 的方法進行驗證并解析 token,拿到上面進行 sign() 的數據 {name: result.name, _id: result._id},并賦值給 ctx.state.user,在控制器中便可以直接通過 ctx.state.user 拿到 name 和 _id。

安全性

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

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

總結

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

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

【本文為51CTO專欄作者“林鑫”的原創稿件,轉載請通過微信公眾號聯系作者獲取授權】

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

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

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應用

2018-04-20 16:15:42

Koa2上傳下載

2017-04-18 09:27:14

Visual StudNode.js調試

2022-08-28 16:30:34

Node.jsDocker指令

2015-03-10 10:59:18

Node.js開發指南基礎介紹

2013-11-01 09:34:56

Node.js技術

2023-01-10 14:11:26

2019-07-24 09:28:36

Node.jskoa架構

2011-07-26 11:07:08

JavaScript

2019-05-05 11:47:09

TypeScript開發Node.js

2020-09-04 15:06:04

Docker容器化Node.js

2017-06-20 15:39:58

Koa2 應用動態Swagger文檔

2017-05-10 09:40:57

Ubuntupm2Nginx

2022-12-14 14:40:27

Node.js開發應用程序

2021-03-03 06:39:05

Nodejs前端開發

2021-07-16 04:56:03

NodejsAddon

2012-09-29 11:13:15

Node.JS前端開發Node.js打包
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 毛色毛片免费看 | 免费在线黄 | 日本一区二区高清不卡 | 日本成人在线网址 | 天堂成人国产精品一区 | 国产不卡视频在线 | 午夜精品久久久 | 国产亚洲精品精品国产亚洲综合 | 无码日韩精品一区二区免费 | 欧美成视频 | 欧美电影在线观看网站 | 欧美精品一区二区三区在线 | 九色在线观看 | 国产玖玖 | 亚洲一区二区三区免费在线观看 | 色伊人久久 | 久久精品91久久久久久再现 | 日韩毛片在线免费观看 | 国产精品免费看 | 久久精品二区亚洲w码 | 天天干狠狠干 | 欧美一区二区三区在线 | 国产精品久久久久久一级毛片 | 亚洲精品久久久9婷婷中文字幕 | 国产精品自拍视频 | www国产成人免费观看视频,深夜成人网 | 日韩成人影院在线观看 | 亚州中文字幕 | 国产一区二区影院 | 久久这里只有精品首页 | 成人免费视频播放 | 最近最新中文字幕 | 97精品一区二区 | 精品网站999 | 欧美成人激情 | 欧美黄 片免费观看 | 国产一区二区不卡 | 亚洲精品国产一区 | 亚洲视频一区 | 亚州精品天堂中文字幕 | 99爱国产 |