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

使用Jsencrypt配合axios實(shí)現(xiàn)數(shù)據(jù)傳輸加密

安全 應(yīng)用安全
對(duì)稱加密就是兩邊擁有相同的秘鑰,兩邊都知道如何將密文加密解密。這種加密方式固然很好,但是問題就在于如何讓雙方知道秘鑰。

[[404720]]

本文轉(zhuǎn)載自微信公眾號(hào)「粥里有勺糖」,作者粥里有勺糖。轉(zhuǎn)載本文請(qǐng)聯(lián)系粥里有勺糖公眾號(hào)。

背景

不希望應(yīng)用發(fā)送的數(shù)據(jù)能在 Devtools 中被看到,避免接口被“同行”扒下來,然后被惡意使用

要避免此問題,首先想到的就是對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行一次加密,讓后端自行解密然后處理

盡管js源碼是被瀏覽器公開的,但通過構(gòu)建工具混淆后,在沒有source map的情況下還不不易定位目標(biāo)代碼

期望加密后的樣子傳輸?shù)膬?nèi)容如下

加密方案簡述

對(duì)稱加密

對(duì)稱加密就是兩邊擁有相同的秘鑰,兩邊都知道如何將密文加密解密。

這種加密方式固然很好,但是問題就在于如何讓雙方知道秘鑰。

由于傳輸數(shù)據(jù)都是走的網(wǎng)絡(luò),如果將秘鑰通過網(wǎng)絡(luò)的方式傳遞的話,一旦秘鑰被截獲就沒有加密的意義

非對(duì)稱加密

有公鑰私鑰之分:

  • 公鑰所有人都可以知道,可以將數(shù)據(jù)用公鑰加密,但是將數(shù)據(jù)解密必須使用私鑰解密
  • 私鑰只有分發(fā)放公鑰的一方才知道

這種加密方式就可以完美解決對(duì)稱加密存在的問題

通過對(duì)比,選用保密性好的 非對(duì)稱加密 方案作為加密方案

本文選用 RSA[1] 對(duì)稱加密算法

公私鑰生成

根據(jù)百度經(jīng)驗(yàn)的建議,生成一個(gè)1024位的的秘鑰

這里使用openssl生成,window下建議在Git Bash下使用

私鑰

  1. openssl genrsa -out rsa_1024_priv.pem 1024 

公鑰

  1. openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem 

jsencrypt

  • jsencrypt[2]
  • nodejs-jsencrypt[3]

“使用 Javascript 進(jìn)行RSA加密的解決方案

使用

安裝依賴

  1. # web 
  2. npm i jsencrypt 
  3.  
  4. # node 
  5. npm i nodejs-jsencrypt 

引入

  1. // web 
  2. import JSEncrypt from 'jsencrypt' 
  3.  
  4. // node 
  5. const { JSEncrypt } = require('nodejs-jsencrypt'

公鑰加密方法

  1. // 上述自動(dòng)生成 
  2. const pubKey = '上述生成的公鑰' 
  3.  
  4. function publicEncrypt(str){ 
  5.     const encrypt = new JSEncrypt() 
  6.     encrypt.setPublicKey(pubKey) 
  7.     return encrypt.encrypt(str) 

私鑰解密方法

  1. const privKey = `上述生成的私鑰` 
  2.  
  3. function privDecrypt(str) { 
  4.     const encrypt = new JSEncrypt() 
  5.     encrypt.setPrivateKey(privKey) 
  6.     return encrypt.decrypt(str) 

可以看出API非常簡潔

使用示例

  1. let str = publicEncrypt('hello world'
  2. console.log(str) 
  3. console.log(privDecrypt(str)) 

結(jié)合Axios實(shí)踐

Axios配置

  1. npm i axios 

將加密邏輯放入到axios的請(qǐng)求攔截器中,將原內(nèi)容使用 JSON.stringify處理后再進(jìn)行加密,加密后的內(nèi)容使用value屬性傳遞,如下所示

  1. import axios from "axios"
  2.  
  3. // 引入剛剛編寫的加密方法 
  4. import { publicEncrypt } from "./utils/crypto"
  5.  
  6. const http = axios; 
  7. http.defaults.baseURL = '/api' 
  8. http.defaults.headers = { 
  9.   "content-Type""application/json" 
  10. }; 
  11.  
  12. // 請(qǐng)求攔截器 
  13. http.interceptors.request.use( 
  14.   config => { 
  15.     // 發(fā)送之前操作config 
  16.     // 對(duì)傳遞的 data 進(jìn)行加密 
  17.     config.data = { 
  18.       value:publicEncrypt(JSON.stringify(config.data)) 
  19.     } 
  20.     return config; 
  21.   }, 
  22.   err => { 
  23.     // 處理錯(cuò)誤 
  24.     return Promise.reject(err); 
  25.   } 
  26. ); 
  27. http.interceptors.response.use( 
  28.   response => { 
  29.     // 返回前操作 
  30.     return response.data; 
  31.   }, 
  32.   err => { 
  33.     return Promise.reject(err); 
  34.   } 
  35. ); 
  36.  
  37. export default http; 

服務(wù)端解密示例代碼

這里列舉了兩種,一種直接使用Node.js的http模塊編寫,一種使用Express編寫:

  1. 解密收到的內(nèi)容
  2. 將解密后的內(nèi)容直接返回

http模塊示例

使用data事件與end事件配合,接收傳遞的數(shù)據(jù),然后進(jìn)行解密返回

  1. const http = require('http'
  2.  
  3. // 引入解密方法 
  4. const { privDecrypt } = require('./utils/crypto'
  5.  
  6. const server = http.createServer((req, res) => { 
  7.     res.setHeader('content-type','application/json'
  8.     let buffer = Buffer.alloc(0) 
  9.  
  10.     // 接收傳遞的數(shù)據(jù) 
  11.     req.on('data',(chunk)=>{ 
  12.         buffer = Buffer.concat([buffer, chunk]) 
  13.     }) 
  14.     req.on('end',()=>{ 
  15.         try { 
  16.             // 解密傳遞的數(shù)據(jù) 
  17.             const data = privDecrypt(JSON.parse(buffer.toString('utf-8')).value) 
  18.             res.end(data) 
  19.         } catch (error) { 
  20.             console.log(error); 
  21.             res.end('error')             
  22.         } 
  23.     }) 
  24. }) 
  25.  
  26. // 啟動(dòng) 
  27. server.listen(3000, err => { 
  28.     console.log(`listen 3000 success`); 
  29. }) 

Express示例

配置一個(gè)前置的*路由,解密傳遞的內(nèi)容,然后將其重新綁定到req.body上,供后續(xù)其它路由使用

  1. const express = require('express'
  2. const { privDecrypt } = require('./utils/crypto'
  3.  
  4. const server = express() 
  5.  
  6. server.use(express.urlencoded({ extended: false })) 
  7. server.use(express.json({ strict: true })) 
  8.  
  9. // 首先進(jìn)入的路由 
  10. server.route('*').all((req, res, next) => { 
  11.     console.log(`${req.method}--${req.url}`) 
  12.     req.body = JSON.parse(privDecrypt(req.body.value)) 
  13.     next() 
  14. }) 
  15.  
  16. server.post('/test/demo',(req,res)=>{ 
  17.     // 直接返回實(shí)際的內(nèi)容 
  18.     res.json(req.body) 
  19. }) 
  20.  
  21. // 啟動(dòng) 
  22. server.listen(3000, err => { 
  23.     console.log(`listen 3000 success`); 
  24. }) 

前端代碼示例

使用了 Vite 作為開發(fā)預(yù)覽工具

vite.config.js配置: 只做了請(qǐng)求代理,解決開發(fā)跨域問題

  1. export default { 
  2.     server: { 
  3.         proxy: { 
  4.             '/api': { 
  5.                 target: 'http://localhost:3000'
  6.                 changeOrigin: true
  7.                 rewrite: (path) => path.replace(/^\/api/, ''
  8.             }, 
  9.         } 
  10.     } 

頁面

  1. <body> 
  2.     <button id="send">發(fā)送</button> 
  3.     <hr> 
  4.     <h2></h2> 
  5.     <textarea id="receive" placeholder="接收的內(nèi)容"></textarea> 
  6.     <script type="module" src="./index.js"></script> 
  7. </body> 

 

 

邏輯

  1. import $http from './http' 
  2. const $send = document.getElementById('send'
  3. const $receive = document.getElementById('receive'
  4.  
  5. $send.addEventListener('click',function(){ 
  6.     // 發(fā)送一個(gè)隨機(jī)內(nèi)容 
  7.     $http.post('/test/demo',{ 
  8.         name:'xm'
  9.         age:~~(Math.random()*1000) 
  10.     }).then((res)=>[ 
  11.         updateReceive(res) 
  12.     ]) 
  13. }) 
  14.  
  15. function updateReceive(data){ 
  16.     $receive.value = data instanceof Object?JSON.stringify(data):data 

運(yùn)行結(jié)果

頁面

發(fā)送網(wǎng)絡(luò)請(qǐng)求

請(qǐng)求響應(yīng)內(nèi)容

大功告成,接入十分簡單

完整的示例代碼倉庫[4]

外鏈

[1]RSA: https://baike.baidu.com/item/RSA%E7%AE%97%E6%B3%95/263310

[2]jsencrypt: https://www.npmjs.com/package/jsencrypt

[3]nodejs-jsencrypt: https://www.npmjs.com/package/nodejs-jsencrypt

[4]完整的示例代碼倉庫: https://github.com/ATQQ/demos/tree/main/asymmetric-encryption

 

責(zé)任編輯:武曉燕 來源: 粥里有勺糖
相關(guān)推薦

2011-03-02 11:23:48

2009-05-26 11:24:00

2024-12-31 08:54:38

2009-04-10 23:40:06

2009-05-19 17:05:10

2020-06-12 07:50:15

大數(shù)據(jù)

2009-12-08 11:17:41

WCF雙向通信

2010-04-07 14:54:38

2010-07-13 15:55:12

FTP數(shù)據(jù)傳輸模式

2023-04-12 16:20:00

同步數(shù)據(jù)異步數(shù)據(jù)傳輸

2013-11-26 15:51:45

Android編程藍(lán)牙數(shù)據(jù)傳輸

2015-10-14 09:44:55

TCP網(wǎng)絡(luò)協(xié)議數(shù)據(jù)傳輸

2023-07-12 15:52:28

2009-07-07 16:46:33

數(shù)據(jù)傳輸銅纜結(jié)構(gòu)

2021-12-14 11:01:44

TCPUDP網(wǎng)絡(luò)協(xié)議

2019-09-06 09:11:36

以太網(wǎng)數(shù)據(jù)二層交換

2017-05-04 12:48:18

WOT網(wǎng)易NDC

2022-03-30 15:06:25

數(shù)據(jù)傳輸Harmony源碼分析

2024-08-05 09:31:00

MySQLDTS數(shù)據(jù)

2021-10-08 08:37:38

數(shù)據(jù)傳輸數(shù)據(jù)調(diào)用網(wǎng)絡(luò)協(xié)議
點(diǎn)贊
收藏

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