原需求:
发起HTTP的POST请求的入参格式为接口参数及参数值组成的JSON字符串,
该JSON字符串需进行RSA加密,
接口再使用HttpServletRequest获取参数值后对数据进行RSA解密。
而密钥最高为1024位,这使得加密时的字符串不能超过117个字节,于是需要对加密前的JSON字符串进行按字节分割后放入数组,然后对数组中的每一项分别加密,最后将加密后的数组转成JSON字符串后作为请求体传入。
这时 HttpServletRequest可以先拿到加密后的JSON数组,然后对加密后的JSON数组的每一项分别解密,最后可将解密后的JSON数组的每一项拼接成接口参数及参数值组成的JSON字符串从而实现原需求。
下面是相关代码
RSA加密工具
package com.ieslab.msgpush.util;
import org.springframework.stereotype.Service;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* @description: RSA加密工具
* @author: yiwenli
* @create: 2021-04-29 09:52
**/
public class RSAUtil {
/**
* 获取公钥私钥
*/
public static void initKey() {
try {
Base64.Encoder encoder = Base64.getEncoder();
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,密钥大小为96-1024位
keyPairGen.initialize(1024, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
privateKeyStr = new String(encoder.encode((privateKey.getEncoded())));
publicKeyStr = new String(encoder.encode(publicKey.getEncoded()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* RSA公钥加密
*
* @param str 加密字符串
* @param publicKey 公钥
*/
public static String encrypt(String str, String publicKey) {
try {
Base64.Decoder decoder = Base64.getDecoder();
Base64.Encoder encoder = Base64.getEncoder();
//base64编码的公钥
byte[] decoded = decoder.decode(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = encoder.encodeToString(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* RSA私钥解密
*
* @param str 加密字符串
* @param privateKey 私钥
*/
public static String decrypt(String str, String privateKey) {
try {
Base64.Decoder decoder = Base64.getDecoder();
//64位解码加密后的字符串
byte[] inputByte = decoder.decode(str.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = decoder.decode(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
将加密前的JSON串进行字节分割
/**
* 字符串分解放入Arrays 因为AES加密时的字符串不能超过117个字节
*
* @param paramsJson 完整的参数json字符串
*/
private List<String> getParamJsonArray(String paramsJson) {
List<String> result = new ArrayList<>();
try {
byte[] paramJsonByteArray = URLEncoder.encode(paramsJson, "UTF-8").getBytes("UTF-8");
while(paramJsonByteArray.length > 0) {
if(paramJsonByteArray.length > 117) {
byte[] paramByteArrayAdd = Arrays.copyOfRange(paramJsonByteArray, 0, 117);
result.add(new String(paramByteArrayAdd));
paramJsonByteArray = Arrays.copyOfRange(paramJsonByteArray, 117, paramJsonByteArray.length);
continue;
}
result.add(new String(paramJsonByteArray));
break;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
发送HTTP POST请求
/**
* 发送HTTP POST请求
*
* @param url 请求地址
* @param data 请求参数
*/
public static String httpPost(String url, String data) {
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
httpPost.setEntity(new StringEntity(data, "UTF-8"));
String result = null;
try(CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = httpclient.execute(httpPost)) {
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity, "UTF-8");
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
获取接口参数并解析后转换格式
/**
* 获取接口参数并转换类型
*
* @param request
*/
private JSONObject getParamObject(HttpServletRequest request) {
StringBuilder requestValue = new StringBuilder();
try(InputStream inputStream = request.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
) {
String line;//循环读取
while ((line = reader.readLine()) != null) {
requestValue.append(line);
}
} catch (Exception e){
e.printStackTrace();
}
// 加密后的json数组
List<String> paramJsonInCode = JSON.parseArray(requestValue.toString(), String.class);
StringBuilder paramJson = new StringBuilder();
// 对加密后的json数组的每一项分别解密
for(String paramJsonOneInCode: paramJsonInCode) {
paramJson.append(RSAUtil.decrypt(paramJsonOneInCode, RSAUtil.getPrivateKeyStr()));
}
try {
String paramJsonDecode = URLDecoder.decode(paramJson.toString(), "UTF-8");
return JSON.parseObject(paramJsonDecode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}