成人免费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上傳下載

2022-08-28 16:30:34

Node.jsDocker指令

2017-04-18 09:27:14

Visual StudNode.js調試

2015-03-10 10:59:18

Node.js開發指南基礎介紹

2019-07-24 09:28:36

Node.jskoa架構

2013-11-01 09:34:56

Node.js技術

2023-01-10 14:11:26

2011-07-26 11:07:08

JavaScript

2020-09-04 15:06:04

Docker容器化Node.js

2019-05-05 11:47:09

TypeScript開發Node.js

2017-06-20 15:39:58

Koa2 應用動態Swagger文檔

2022-12-14 14:40:27

Node.js開發應用程序

2017-05-10 09:40:57

Ubuntupm2Nginx

2012-09-29 11:13:15

Node.JS前端開發Node.js打包

2022-08-22 07:26:32

Node.js微服務架構

2021-07-30 11:20:53

JavaScriptNode.jsWeb Develop
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 超碰在线97国产 | 亚洲精品2区 | 午夜一区二区三区视频 | www.色.com| 欧美视频三级 | 九九九视频在线观看 | 成人婷婷 | 91精品国产色综合久久 | 亚洲电影免费 | 午夜久久久久 | 中文字幕三区 | 日韩一区二区视频 | 日韩视频一区二区 | 免费人成在线观看网站 | 欧美xxxx性| 国产日韩久久 | 99视频在线免费观看 | 电影午夜精品一区二区三区 | 精品亚洲一区二区三区四区五区 | 精品久| 伊人国产精品 | 狠狠干狠狠操 | 成人午夜免费网站 | 国产激情精品一区二区三区 | a黄毛片 | 亚州春色 | 日本一区二区视频 | 国外成人在线视频 | 黄色在线观看网址 | 欧美日韩综合精品 | 国产精品久久久久久久久久 | h视频在线播放 | 亚洲福利| 91国内产香蕉 | 久久久国产一区 | av黄色免费在线观看 | 亚洲精品一二三 | 一区二区三区四区国产 | 91麻豆精品国产91久久久久久久久 | 一区二区三区精品视频 | 久久不卡区 |