前后端接口AES+RSA混合加解密详解(vue+SpringBoot)  前后端接口AES+RSA混合加解密 一、AES加密原理和为什么不使用AES加密 二、RSA加密原理和为什么不使用rsa加密 三、AES和RSA混合加密的原理 四、代码样例 前端 1. 请求增加加密标识 2. 前端加密工具类 3.前端axios请求统一封装,和返回统一封装 后端 1.后端加密工具类 2. 请求的返回实体封装 3. 配置过滤器对请求进行加解密操作 4.过滤器注册 5. 获取RSA公钥接口 总结:   
 
     为什么需要对前后端接口加解密?主要是甲方要求。
  AES是最常见的对称加密算法,加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合,且加密长文本比较方便。缺点是密钥的传输比较麻烦,只能将一把公钥分别在前后端代码中各存放一份,还有一个遇到的问题下面会讲到,那就是美国对AES加密密钥长度的限制。优点是加密效率高,缺点是安全性低。
RSA也就是非对称加密算法,是使用不同密钥进行加密和解密的算法,也称为公私钥加密。公钥和私钥是同时生成的,公钥用来加密,私钥用来解密,加解密的密钥是成对出现。但是不推荐用RSA加密请求报文,因为RSA加密后的报文会很长,经常会出现超过请求体长度限制。优点是安全性高,缺点是RSA的加密效率低。
我们可以结合两者的优点,AES的加密效率高,那我们可以使用aes来加密报文,而RSA的灵活性和安全性来加密aes的密钥。总的思路就是利用RSA来加密传输AES的密钥,用 AES的密钥来加密请求报文。
  首先这个功能我们的出发点是可以灵活配置,所以我们在需要加密的请求头添加一个加密标识代码如下:
import  axios from  '@common/plugins/Axios' saveStudent :  data  =>  { return  axios. request ( { url :  ` /demo/saveStudent ` , method :  'post' , headers :  { isEncrypt :  1 } , data} ) } 
import  JSEncrypt from  'jsencrypt' 
import  CryptoJS from  'crypto-js' 
export  function  rsaEncrypt ( Str,  afterPublicKey )  { const  encryptor =  new  JSEncrypt ( ) encryptor. setPublicKey ( afterPublicKey)  return  encryptor. encrypt ( Str)  
} 
export  function  rsaDecrypt ( Str,  frontPrivateKey )  { const  encryptor =  new  JSEncrypt ( ) encryptor. setPrivateKey ( frontPrivateKey)  return  encryptor. decrypt ( Str)  
} export  function  aesEncrypt ( aeskey,  Str )  { var  key =  CryptoJS. enc. Utf8. parse ( aeskey) var  srcs =  CryptoJS. enc. Utf8. parse ( Str) var  encrypted =  CryptoJS. AES . encrypt ( srcs,  key,  { mode :  CryptoJS. mode. ECB , padding :  CryptoJS. pad. Pkcs7} ) return  encrypted. toString ( ) 
} export  function  aesDecrypt ( aeskey,  Str )  { var  key =  CryptoJS. enc. Utf8. parse ( aeskey) var  decrypt =  CryptoJS. AES . decrypt ( Str,  key,  { mode :  CryptoJS. mode. ECB , padding :  CryptoJS. pad. Pkcs7} ) return  CryptoJS. enc. Utf8. stringify ( decrypt) . toString ( ) 
} 
export  function  get16RandomNum ( )  { var  chars =  [        '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' ,  'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 
'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' ] var  nums =  '' for  ( var  i =  0 ;  i <  16 ;  i++ )  { var  id =  parseInt ( Math. random ( )  *  61 ) nums +=  chars[ id] } return  nums
} 
export  function  getRsaKeys ( )  { return  new  Promise ( ( resolve,  reject )  =>  { window. crypto. subtle. generateKey ( { name :  'RSA-OAEP' , modulusLength :  2048 ,  publicExponent :  new  Uint8Array ( [ 0x01 ,  0x00 ,  0x01 ] ) , hash :  {  name :  'SHA-512'  }  } , true ,  [ 'encrypt' ,  'decrypt' ]  ) . then ( function ( key )  { window. crypto. subtle. exportKey ( 'pkcs8' ,  key. privateKey) . then ( function ( keydata1 )  { window. crypto. subtle. exportKey ( 'spki' ,  key. publicKey) . then ( function ( keydata2 )  { var  privateKey =  RSA2text ( keydata1,  1 ) var  publicKey =  RSA2text ( keydata2) resolve ( {  privateKey,  publicKey } ) } ) . catch ( function ( err )  { reject ( err) } ) } ) . catch ( function ( err )  { reject ( err) } ) } ) . catch ( function ( err )  { reject ( err) } ) } ) 
} 
function  RSA2text ( buffer,  isPrivate =  0  )  { var  binary =  '' var  bytes =  new  Uint8Array ( buffer) var  len =  bytes. byteLengthfor  ( var  i =  0 ;  i <  len;  i++ )  { binary +=  String. fromCharCode ( bytes[ i] ) } var  base64 =  window. btoa ( binary) let  text =  base64. replace ( / [^\x00-\xff] / g ,  '$&\x01' ) . replace ( / .{64}\x01? / g ,  '$&\n' ) return  text
} 
import  Axios from  'axios' 
import  {  getRsaKeys,  rsaEncrypt,  rsaDecrypt,  aesDecrypt,  aesEncrypt,  get32RandomNum }  from  '@common/util' 
const  instance =  Axios. create ( { headers :  { x_requested_with :  'XMLHttpRequest' } 
} ) 
let  frontPrivateKey
instance. interceptors. request. use ( async  config  =>  { if  ( sessionStorage. getItem ( 'X-Access-Token' ) )  { config. headers[ 'X-Access-Token' ]  =  sessionStorage. getItem ( 'X-Access-Token' ) } if  ( config. headers[ 'isEncrypt' ] )  { config. headers[ 'Content-Type' ]  =  'application/json;charset=utf-8' if  ( config. method ===  'post'  ||  config. method ===  'put' )  { const  {  privateKey,  publicKey }  =  await  getRsaKeys ( ) let  afterPublicKey =  sessionStorage. getItem ( 'afterPublicKey' ) frontPrivateKey =  privateKeylet  aesKey =  get16RandomNum ( ) let  aesKeyByRsa =  rsaEncrypt ( aesKey,  afterPublicKey) if  ( config. data)  { let  data =  aesEncrypt ( aesKey,  JSON . stringify ( config. data) ) config. data =  { data :  data, aeskey :  aesKeyByRsa, frontPublicKey :  publicKey} } if  ( config. params)  { let  data =  aesEncrypt ( aesKey,  JSON . stringify ( config. params) ) config. params =  { params :  data, aeskey :  aesKeyByRsa, frontPublicKey :  publicKey} } } } config. url = "你的后端接口请求地址"  +  config. urlreturn  config} , err  =>  { return  Promise. reject ( err) } 
) 
instance. interceptors. response. use ( response  =>  { let  aesKeyByRsa =  response. data. aesKeyByRsaif  ( aesKeyByRsa)  { let  aesKey =  rsaDecrypt ( aesKeyByRsa,  frontPrivateKey) response. data. data =  JSON . parse ( JSON . parse ( aesDecrypt ( aesKey,  response. data. data) ) ) return  response. data} else {  return  response}       } } , error  =>  { if  ( error. response. status ===  500 )  { const  {  data }  =  erro