滿滿干貨(rsa加密算法數(shù)學(xué)原理)rsa加密算法的數(shù)學(xué)基礎(chǔ),RSA+AES實(shí)現(xiàn)接口驗(yàn)簽和參數(shù)加密,目前不能發(fā)快遞的地方,
目錄:
1.rsa加密算法原理數(shù)學(xué)例子
2.rsa加密算法應(yīng)用
3.rsa加密算法
4.rsa算法是什么加密算法的基礎(chǔ)
5.rsa算法加密和解密例題
6.簡述rsa加密算法的工作原理
7.rsa加密解密算法原理
8.rsa加密算法流程圖
9.rsa加密算法是什么密碼
10.rsa加密算法原理介紹
1.rsa加密算法原理數(shù)學(xué)例子
RSA非對(duì)稱加密RSA是一種常用的非對(duì)稱加密算法,加密和加密使用不同的密鑰,常用于要求安全性較高的加密場(chǎng)景,比如接口的驗(yàn)簽和接口數(shù)據(jù)的加密與解密與非對(duì)稱加密算法對(duì)比,其安全性較高,但是加密性能卻比較低,不適合高并發(fā)場(chǎng)景,一般只加密少量的數(shù)據(jù)。
2.rsa加密算法應(yīng)用
AES對(duì)稱加密AES是一種最常mongodbregex見的對(duì)稱加密算法(微信小程序加密傳輸就是用這個(gè)加密算法的),加密和解密使用的是相同的密鑰其加密性能好,加密解密速度非???,內(nèi)存需求低,適用于經(jīng)常發(fā)送數(shù)據(jù)的場(chǎng)合RSA+AES實(shí)現(xiàn)接口驗(yàn)簽和請(qǐng)求參數(shù)的加密與解密。
3.rsa加密算法
背景:做為程序猿,我們經(jīng)常需要在我們自己開發(fā)的系統(tǒng)上,開發(fā)一些接口供第三方調(diào)用,那么這個(gè)時(shí)候,對(duì)我們接口的安全性要求就比較高了,尤其是那種需要傳輸比較私密的信息的時(shí)候,其對(duì)安全性的要求就更高了實(shí)現(xiàn)思路調(diào)用方:
4.rsa算法是什么加密算法的基礎(chǔ)
使用AES對(duì)稱加密算法對(duì)業(yè)務(wù)請(qǐng)求參數(shù)進(jìn)行加密后傳輸使用RSA非對(duì)稱加密算法對(duì)AES的密鑰進(jìn)行公鑰加密后傳輸使用RSA的私鑰對(duì)請(qǐng)求參數(shù)mongodbregex進(jìn)行簽名接收方:獲取到請(qǐng)求參數(shù)后,對(duì)參數(shù)進(jìn)行驗(yàn)簽和業(yè)務(wù)參數(shù)的解密問題:為什么要對(duì)AES的密鑰進(jìn)行RSA公鑰加密后傳輸?
5.rsa算法加密和解密例題
AES是對(duì)稱加密算法,加密和解密的密鑰都是同一個(gè),為了防止被別人惡意獲取到該密鑰,然后對(duì)我們的業(yè)務(wù)請(qǐng)求參數(shù)進(jìn)行解密,我們需要將AES密鑰進(jìn)行非對(duì)稱加密后再進(jìn)行傳輸代碼實(shí)現(xiàn)
6.簡述rsa加密算法的工作原理
>org.bouncycastlebcpkix-jdk15on1.56
7.rsa加密解密算法原理
>com.fasterxml.jackson.corejackson-databind
8.rsa加密算法流程圖
2.9.8org.codehaus.jacksmongodbregexon
9.rsa加密算法是什么密碼
jackson-core-asl1.8.3請(qǐng)求和接收的實(shí)體對(duì)象@Data
10.rsa加密算法原理介紹
publicclass JsonRequest { //接口id 可空privateString serviceId; //請(qǐng)求唯一id 非空privateString requestId;
//商戶id 非空privateString appId; //參數(shù)簽名 非空privateString sign; //對(duì)稱加密key 非空privateString aseKey;
//時(shí)間戳,精確到毫秒 非空pmongodbregexrivate long timestamp; //請(qǐng)求的業(yè)務(wù)參數(shù)(AES加密后傳入) 可空privateString body; }serviceId:服務(wù)id(接口id)。
接口設(shè)計(jì)分為兩種,一種是所有的調(diào)用方針對(duì)類似的業(yè)務(wù),都調(diào)用的是同一接口地址,然后內(nèi)部系統(tǒng)根據(jù)serviceId去判斷具體是要調(diào)用哪個(gè)業(yè)務(wù)方法;另一種是針對(duì)不同的調(diào)用方,開發(fā)不同的接口,接口地址也是不一樣,那么這個(gè)時(shí)候就可以不要serviceId這個(gè)字段。
本章是使用第二種方式,所以serviceId可以不要(可空)requestId:請(qǐng)求唯一id方便查詢定位某個(gè)請(qǐng)求和防止同個(gè)請(qǐng)求多次調(diào)用appmongodbregexId:商戶id,即我們會(huì)給調(diào)用方分配一個(gè)這樣的id,并且將這個(gè)id與調(diào)用方的信息進(jìn)行關(guān)聯(lián),比如“通過appId查詢出調(diào)用方的加密密鑰等”。
aseKey:是AES對(duì)稱加密的密鑰用于解密業(yè)務(wù)請(qǐng)求參數(shù)這里要先用RSA公鑰對(duì)aseKey進(jìn)行加密后傳輸timestamp:請(qǐng)求時(shí)間戳可以用該字段,對(duì)請(qǐng)求的時(shí)間合法性進(jìn)行校驗(yàn)(如:過濾掉請(qǐng)求時(shí)間不在當(dāng)前時(shí)間的正負(fù)10分鐘范圍內(nèi)的請(qǐng)求)。
body:請(qǐng)求的業(yè)務(wù)參數(shù)對(duì)請(qǐng)求的業(yè)務(wù)參數(shù)AES加密后再賦值A(chǔ)ES工具類publicclassAESUtil{ /** * 加密 * @param content 加密文本 mongodbregex * 。
@param key 加密密鑰,appSecret的前16位 * @param iv 初始化向量,appSecret的后16位 * @return * @throws Exception */
publicstatic String encrypt(String content, String key, String iv)throws Exception { byte[] raw = key.getBytes(); SecretKeySpec skeySpec =
new SecremongodbregextKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //"算法/模式/補(bǔ)碼方式"
IvParameterSpec ivParam = new IvParameterSpec(iv.getBytes()); //使用CBC模式,需要一個(gè)向量iv,可增加加密算法的強(qiáng)度 cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParam);
byte[] encrypted = cipher.doFinal(content.gemongodbregextBytes()); returnnew BASE64Encoder().encode(encrypted); }
publicstatic String decrypt(String content, String key, String iv)throws Exception { byte[] raw = key.getBytes(); SecretKeySpec skeySpec =
new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstancmongodbregexe("AES/CBC/PKCS5Padding "); //"算法/模式/補(bǔ)碼方式"
IvParameterSpec ivParam = new IvParameterSpec(iv.getBytes()); //使用CBC模式,需要一個(gè)向量iv,可增加加密算法的強(qiáng)度 cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParam);
byte[] encrypted = new BASE64Decoder().decodeBuffer(content); //先用base64解密byte[] original = cipher.doFinalmongodbregex(encrypted);
returnnew String(original); } publicstaticvoidmain(String[] args)throws Exception { String encrypt = AESUtil.encrypt(
"你好?。。?!", "1234567890123456", "1234567890123456"); String decrypt = AESUtil.decrypt(encrypt,
"1234567890123456", "1234567890123456"); mongodbregex System.out.println(decrypt); } RSA工具類 public class
RSAUtil{ /** * 定義加密方式 */ private final staticString KEY_RSA = "RSA"; /** * 定義簽名算法 */
private final staticString KEY_RSA_SIGNATURE = "MD5withRSA"; /** mongodbregex* 定義公鑰算法 */ private final
staticString KEY_RSA_PUBLICKEY = "RSAPublicKey"; /** * 定義私鑰算法 */ private final static
String KEY_RSA_PRIVATEKEY = "RSAPrivateKey"; static { Security.addProvider(new BouncyCastleProvider()); }
/** mongodbregex* 初始化密鑰 */ public staticMap init() { Map map =
null; try { KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_RSA); generator.initialize(
2048); KeyPair keyPair = generator.generateKeyPair(); // 公鑰 RSAPublicKey publicKemongodbregexy = (RSAPublicKey) keyPair.getPublic();
// 私鑰 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 將密鑰封裝為map
map = new HashMap<>(); map.put(KEY_RSA_PUBLICKEY, publicKey); map.put(KEY_RSA_PRIVATEKEY, privateKey); }
catch (NoSuchAlgorithmException e)mongodbregex { e.printStackTrace(); } return map; }
/** * 公鑰加密 * * @param data 待加密數(shù)據(jù) * @param key 公鑰 */ public static byte[] encryptByPublicKey(
String data, String key) { byte[] result = null; try { byte[] bytmongodbregexes = decryptBase64(key);
// 取得公鑰 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); KeyFactory factory = KeyFactory.getInstance(KEY_RSA); PublicKey publicKey = factory.generatePublic(keySpec);
// 對(duì)數(shù)據(jù)加密 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding",mongodbregex "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encode = cipher.doFinal(data.getBytes());
// 再進(jìn)行Base64加密 result = Base64.encode(encode); } catch (Exception e) { e.printStackTrace(); }
return result; } /** * 私鑰解密 mongodbregex * * @param data 加密數(shù)據(jù) * @param key 私鑰 */
public staticString decryptByPrivateKey(byte[] data, String key) { String result = null;
try { // 對(duì)私鑰解密 byte[] bytes = decryptBase64(key); // 取得私鑰 PKCS8EncodedKeySpec keySpec =
new PKCS8EncodedKemongodbregexySpec(bytes); KeyFactory factory = KeyFactory.getInstance(KEY_RSA); PrivateKey privateKey = factory.generatePrivate(keySpec);
// 對(duì)數(shù)據(jù)解密 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC"); cipher.init(Cipher.DECRYPT_MODE, privateKey);
// 先Base64解密 bmongodbregexyte[] decoded = Base64.decode(data); result = newString(cipher.doFinal(decoded)); }
catch (Exception e) { e.printStackTrace(); } return result; } /** * 獲取公鑰 */
public staticString getPublicKey(Map map) { String str = "";mongodbregex try
{ Key key = (Key) map.get(KEY_RSA_PUBLICKEY); str = encryptBase64(key.getEncoded()); }
catch (Exception e) { e.printStackTrace(); } return str; } /** * 獲取私鑰 */
public staticString getPrivateKey(Map map) { mongodbregex String str = ""; try
{ Key key = (Key) map.get(KEY_RSA_PRIVATEKEY); str = encryptBase64(key.getEncoded()); }
catch (Exception e) { e.printStackTrace(); } return str; } /** * 用私鑰對(duì)信息生成數(shù)字簽名 * *
@param datamongodbregex 加密數(shù)據(jù) * @param privateKey 私鑰 */ public staticString sign(byte[] data,
String privateKey) { String str = ""; try { // 解密由base64編碼的私鑰 byte[] bytes = decryptBase64(privateKey);
// 構(gòu)造PKCS8EncodedKeySpec對(duì)象 PKCS8EncodedKeySpec pkcs = new PKCS8EmongodbregexncodedKeySpec(bytes);
// 指定的加密算法 KeyFactory factory = KeyFactory.getInstance(KEY_RSA); // 取私鑰對(duì)象 PrivateKey key = factory.generatePrivate(pkcs);
// 用私鑰對(duì)信息生成數(shù)字簽名 Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE); signature.initSign(key); signamongodbregexture.update(data); str = encryptBase64(signature.sign()); }
catch (Exception e) { e.printStackTrace(); } return str; } /** * 校驗(yàn)數(shù)字簽名 * *
@param data 加密數(shù)據(jù) * @param publicKey 公鑰 * @param sign 數(shù)字簽名 * @mongodbregexreturn 校驗(yàn)成功返回true,失敗返回false */
public static boolean verify(byte[] data, String publicKey, String sign) { boolean flag =
false; try { // 解密由base64編碼的公鑰 byte[] bytes = decryptBase64(publicKey);
// 構(gòu)造X509EncodedKeySpec對(duì)象 X509EncodedKeySpec keySpec = new X50mongodbregex9EncodedKeySpec(bytes);
// 指定的加密算法 KeyFactory factory = KeyFactory.getInstance(KEY_RSA); // 取公鑰對(duì)象 PublicKey key = factory.generatePublic(keySpec);
// 用公鑰驗(yàn)證數(shù)字簽名 Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE); signature.initVerify(key); sigmongodbregexnature.update(data); flag = signature.verify(decryptBase64(sign)); }
catch (Exception e) { e.printStackTrace(); } return flag; } /** * BASE64 解密 * *
@param key 需要解密的字符串 * @return 字節(jié)數(shù)組 */ public stmongodbregexatic byte[] decryptBase64(String key) throws Exception {
return Base64.decode(key); } /** * BASE64 加密 * * @param key 需要加密的字節(jié)數(shù)組 *
@return 字符串 */ public staticString encryptBase64(byte[] key) throws Exception { return
newString(Basemongodbregex64.encode(key)); } /** * 按照紅黑樹(Red-Black tree)的 NavigableMap 實(shí)現(xiàn) * 按照字母大小排序 */
public staticMap sort(Map map) { if (map == null) {
returnnull; } Map result = new TreeMap<>((Comparator) (o1, o2) -> {
return o1.compareTo(o2); }); mongodbregex result.putAll(map); return result; } /** * 組合參數(shù) * *
@param map * @return 如:key1Value1Key2Value2.... */ public staticString groupStringParam(
Map map) { if (map == null) { returnnull; } StringBmongodbregexuffer sb =
new StringBuffer(); for (Map.Entry item : map.entrySet()) { if (item.getValue() !=
null) { sb.append(item.getKey()); if (item.getValue() instanceof List) { sb.append(
JSON.toJSONString(item.getValue())); } else { sb.append(item.getValuemongodbregex()); } } }
return sb.toString(); } /** * bean轉(zhuǎn)map * @param obj * @return */ public
staticMap bean2Map(Object obj) { if (obj == null) { returnnull; }
Map map = new HashMap<>(); try { mongodbregexBeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName();
// 過濾class屬性if (!key.equals("class")) { // 得到prmongodbregexoperty對(duì)應(yīng)的getter方法 Method getter = property.getReadMethod();
Object value = getter.invoke(obj); if (StringUtils.isEmpty(value)) {
continue; } map.put(key, value); } } }
catch (Exception e) { e.printStackTrace(); } return mapmongodbregex; } /** * 按照紅黑樹(Red-Black tree)的 NavigableMap 實(shí)現(xiàn) * 按照字母大小排序 */
public staticMap sort(Map map) { if (map == null) {
returnnull; } Map result = new TreeMap<>((Comparator) (o1, o2) -> {
return o1.compareTo(o2); }); result.putmongodbregexAll(map); return result; } /** * 組合參數(shù) * *
@param map * @return 如:key1Value1Key2Value2.... */ public staticString groupStringParam(
Map map) { if (map == null) { returnnull; } StringBuffer sb =
new SmongodbregextringBuffer(); for (Map.Entry item : map.entrySet()) { if (item.getValue() !=
null) { sb.append(item.getKey()); if (item.getValue() instanceof List) { sb.append(
JSON.toJSONString(item.getValue())); } else { sb.append(item.getValue()); } mongodbregex } }
return sb.toString(); } /** * bean轉(zhuǎn)map * @param obj * @return */ public
staticMap bean2Map(Object obj) { if (obj == null) { returnnull; }
Map map = new HashMap<>(); try { BeanInfo beanInmongodbregexfo = Introspector.getBeanInfo(obj.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName();
// 過濾class屬性if (!key.equals("class")) { // 得到property對(duì)應(yīng)的gettermongodbregex方法 Method getter = property.getReadMethod();
Object value = getter.invoke(obj); if (StringUtils.isEmpty(value)) {
continue; } map.put(key, value); } } }
catch (Exception e) { e.printStackTrace(); } return map; } mongodbregex public
staticvoid main(String[] args) throws Exception { System.out.println("公鑰加密======私鑰解密");
String str = "Longer程序員"; byte[] enStr = RSAUtil.encryptByPublicKey(str, publicKey);
String miyaoStr = HexUtils.bytesToHexString(enStr); byte[] bytes = HexUtils.hexStringToBytesmongodbregex(miyaoStr);
String decStr = RSAUtil.decryptByPrivateKey(bytes, privateKey); System.out.println("加密前:" + str +
"\n\r解密后:" + decStr); System.out.println("\n\r"); System.out.println("私鑰簽名======公鑰驗(yàn)證"
); String sign = RSAUtil.sign(str.getBytes(), privateKey); System.mongodbregexout.println("簽名:\n\r"
+ sign); boolean flag = RSAUtil.verify(str.getBytes(), publicKey, sign); System.out.println(
"驗(yàn)簽結(jié)果:\n\r" + flag); } jackson工具類import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.mongodbregexextern.slf4j.Slf4j; import org.codehaus.jackson.type.TypeReference; import org.springframework.util.StringUtils;
import java.io.IOException; import java.util.ArrayList; import java.util.List; @Slf4jpublicclassJacksonUtil
{ private static ObjectMapper mongodbregexobjectMapper = new ObjectMapper(); /** * 對(duì)象轉(zhuǎn)換成json * *
@param obj * @param * @return */public static String beanToJson(T obj) {
if (obj == null) { returnnull; } try { return obj instanceof String ? (String) obj : mongodbregexobjectMapper.writeValueAsString(obj); }
catch (Exception e) { log.error("beanToJson error", e); e.printStackTrace();
returnnull; } } /** * 將JSON字符串根據(jù)指定的Class反序列化成Java對(duì)象 * * @param json JSON字符串 * 。
@param pojoClass Java對(duì)象Clmongodbregexass * @return 反序列化生成的Java對(duì)象 * @throws Exception 如果反序列化過程中發(fā)生錯(cuò)誤,將拋出異常 */
public static Object decode(String json, Class pojoClass) throws Exception { try
{ return objectMapper.readValue(json, pojoClass); } catch (Exception e) {
throw e; } mongodbregex } /** * 將JSON字符串根據(jù)指定的Class反序列化成Java對(duì)象 * * @param json JSON字符串 * 。
@param reference 類型引用 * @return 反序列化生成的Java對(duì)象 * @throws Exception 如果反序列化過程中發(fā)生錯(cuò)誤,將拋出異常 */
public static Object decode(String json, TypeReference reference) throws Excmongodbregexeption { try {
return objectMapper.readValue(json, reference.getClass()); } catch (Exception e) {
throw e; } } /** * 將Java對(duì)象序列化成JSON字符串 * * @param obj 待序列化生成JSON字符串的Java對(duì)象 * 。
@return JSON字符串 * @throws Exception 如果序列化過程中發(fā)生mongodbregex錯(cuò)誤,將拋出異常 */public static String encode(Object obj) throws Exception {
try { return objectMapper.writeValueAsString(obj); } catch (Exception e) {
throw e; } } /** * 對(duì)象轉(zhuǎn)換成格式化的json * * @param obj * @param *
@return mongodbregex */public static String beanToJsonPretty(T obj) { if (obj == null) {
returnnull; } try { return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj); }
catch (Exception e) { log.error("beanToJsmongodbregexonPretty error", e); e.printStackTrace();
returnnull; } } /** * 將json轉(zhuǎn)換成對(duì)象Class * * @param str * @param clazz *
@param * @return */public static T jsonToBean(String str, Class clazz) {
if (StringUtils.isEmpty(str)mongodbregex || clazz == null) { returnnull; } try {
return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz); } catch (Exception e) { log.error(
"jsonToBean error", e); e.printStackTrace(); returnnull; } }
/** mongodbregex* 將json轉(zhuǎn)換為對(duì)象集合 * * @param str * @param clazz * @param * @return
*/public static List jsonToBeanList(String str, Class clazz) { if (StringUtils.isEmpty(str) || clazz ==
null) { returnnull; } JavaType javaType = getCollectionType(ArmongodbregexrayList.class
, clazz);try { return objectMapper.readValue(str, javaType); } catch (IOException e) { log.error(
"jsonToBeanList error", e); e.printStackTrace(); returnnull; } }
public static JavaType getCollectionType(Class collectionClass, Class.mongodbregex.. elementClasses) {
return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses); } }
加密解密驗(yàn)簽名流程演示 public classRequestTest{ public staticvoid main(String[] args) { /****先給調(diào)用方分配一組RSA密鑰和一個(gè)appId****/
//初始化RSA密鑰Map init = RSAUtil.initmongodbregex(); //私鑰String privateKey = RSAUtil.getPrivateKey(init);
//公鑰String publicKey = RSAUtil.getPublicKey(init); //appId,32位的uuidString appId = getUUID32();
/****先給調(diào)用方分配一組RSA密鑰和一個(gè)appId****//*****調(diào)用方(請(qǐng)求方)*****///業(yè)務(wù)參數(shù)Map businessParams = new HashMap<>(); businessParams.put(
"name","Lonmongodbregexger"); businessParams.put("job","程序猿"); businessParams.put("hobby","打籃球"); JsonRequest jsonRequest =
new JsonRequest(); jsonRequest.setRequestId(getUUID32()); jsonRequest.setAppId(appId); jsonRequest.setTimestamp(System.currentTimeMillis());
//使用appId的前mongodbregex16位作為AES密鑰,并對(duì)密鑰進(jìn)行rsa公鑰加密String aseKey = appId.substring(0, 16); byte[] enStr = RSAUtil.encryptByPublicKey(aseKey, publicKey);
String aseKeyStr = HexUtils.bytesToHexString(enStr); jsonRequest.setAseKey(aseKeyStr);
//請(qǐng)求的業(yè)務(wù)參數(shù)進(jìn)行加密String body = ""; try { body = AESUtil.encrymongodbregexpt(JacksonUtil.beanToJson(businessParams), aseKey, appId.substring(
16)); } catch (Exception e) { thrownew RuntimeException("報(bào)文加密異常", e); } jsonRequest.setBody(body);
//簽名Map paramMap = RSAUtil.bean2Map(jsonRequest); paramMap.remove("sign");
// 參數(shù)排序Map sortedMap mongodbregex= RSAUtil.sort(paramMap); // 拼接參數(shù):key1Value1key2Value2String
urlParams = RSAUtil.groupStringParam(sortedMap); //私鑰簽名String sign = RSAUtil.sign(HexUtils.hexStringToBytes(urlParams), privateKey); jsonRequest.setSign(sign);
/*****調(diào)用方(請(qǐng)求方)*****//*****接收方(自己的系統(tǒng))*****///參數(shù)判空(略)//appImongodbregexd校驗(yàn)(略)//本條請(qǐng)求的合法性校驗(yàn)《唯一不重復(fù)請(qǐng)求;時(shí)間合理》(略)//驗(yàn)簽Map
, Object> paramMap2 = RSAUtil.bean2Map(jsonRequest); paramMap2.remove("sign"); //參數(shù)排序
Map sortedMap2 = RSAUtil.sort(paramMap2); //拼接參數(shù):key1Value1key2Value2String urlParams2 = RSAUtil.groupStringParam(sortedMap2);
//簽名驗(yàn)證 boolean mongodbregexverify = RSAUtil.verify(HexUtils.hexStringToBytes(urlParams2), publicKey, jsonRequest.getSign());
if (!verify) { thrownew RuntimeException("簽名驗(yàn)證失敗"); } //私鑰解密,獲取aseKeyString
aseKey2 = RSAUtil.decryptByPrivateKey(HexUtils.hexStringToBytes(jsonRequest.getAseKey()), privateKey);
ifmongodbregex (!StringUtils.isEmpty(jsonRequest.getBody())) { // 解密請(qǐng)求報(bào)文String requestBody = "";
try { requestBody = AESUtil.decrypt(jsonRequest.getBody(), aseKey, jsonRequest.getAppId().substring(
16)); } catch (Exception e) { thrownew RuntimeException("請(qǐng)求參數(shù)解密異常"); } mongodbregex System.out.println(
"業(yè)務(wù)參數(shù)解密結(jié)果:"+requestBody); } /*****接收方(自己的系統(tǒng))*****/ } public staticString getUUID32() {
String uuid = UUID.randomUUID().toString(); uuid = uuid.replace("-", ""); return uuid; } }
執(zhí)行結(jié)果:業(yè)務(wù)參數(shù)解密結(jié)果:{"name":"Longer","job":"程mongodbregex序猿","hobby":"打籃球"} 到此,調(diào)用方要做的和接收方做的其實(shí)都已經(jīng)清楚了調(diào)用方:1.業(yè)務(wù)參數(shù)進(jìn)行AES對(duì)稱加密2.AES密鑰進(jìn)行RSA非對(duì)稱加密
3.使用RSA生成簽名接收方:驗(yàn)證簽名AES密鑰解密業(yè)務(wù)參數(shù)解密請(qǐng)求參數(shù)的統(tǒng)一處理上面講到,我們接受的請(qǐng)求對(duì)象是JsonRequst對(duì)象,里面除了body成員變量是跟業(yè)務(wù)相關(guān),其他成員變量(sericeId,appId等)都是與業(yè)務(wù)不相關(guān)的。
那么,如果我們?cè)赾ontroller層用JsonRequest對(duì)象去接收請(qǐng)求參數(shù)的話,其實(shí)是不那么規(guī)范的那么我們能不能對(duì)請(qǐng)求參數(shù)進(jìn)行統(tǒng)一處理,使得傳到controller層的參數(shù)只是跟業(yè)mongodbregex務(wù)相關(guān)的參數(shù),并且在controller層也無需關(guān)注加密解密和驗(yàn)簽的東西。
實(shí)現(xiàn)方法:使用過濾器,攔截請(qǐng)求,并對(duì)請(qǐng)求參數(shù)進(jìn)行統(tǒng)一處理(加密解密,驗(yàn)簽等)自定義request對(duì)象(新增類繼承HttpServletRequestWrapper類),對(duì)請(qǐng)求參數(shù)進(jìn)行過濾處理,使得controller只接受業(yè)務(wù)參數(shù)。
問題:為什么需要自定義request對(duì)象?因?yàn)楂@取post請(qǐng)求傳遞的json對(duì)象,需要用request對(duì)象流取獲取,而一旦我們調(diào)用了request.getInputStream()方法后,流將會(huì)自動(dòng)關(guān)閉,那么到了我們的controller層就不能再獲取到請(qǐng)求參數(shù)了。
自定義request對(duì)象immongodbregexport javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import
java.io.*; import java.nio.charset.Charset; mongodbregex publicclassRequestWrapperextendsHttpServletRequestWrapper
{ privatebyte[] body; publicRequestWrapper(HttpServletRequest request)throws IOException {
super(request); String sessionStream = getBodyString(request); body = sessionStream.getBytes(Charset.forName(
"UmongodbregexTF-8")); } public String getBodyString(){ returnnew String(body, Charset.forName("UTF-8"
)); } publicvoidsetBodyString(byte[] bodyByte){ body = bodyByte; } /** * 獲取請(qǐng)求Body * *
@param request * @return mongodbregex */public String getBodyString(final ServletRequest request){ StringBuilder sb =
new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null;
try { inputStream = cloneInputStream(request.getInputStream()); reader = new BufferedReader(
nemongodbregexw InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = "";
while ((line = reader.readLine()) != null) { sb.append(line); } }
catch (IOException e) { e.printStackTrace(); } finally { if (inputStream !=
null) { try { mongodbregex inputStream.close(); } catch (IOException e) { e.printStackTrace(); } }
if (reader != null) { try { reader.close(); } catch
(IOException e) { e.printStackTrace(); } } }
return sb.toString(); } /mongodbregex** * Description: 復(fù)制輸入流
* * @param inputStream *@return
*/public InputStream cloneInputStream(ServletInputStream inputStream){ ByteArrayOutputStream byteArrayOutputStream =new ByteArrayOutputStream(); byte[] buffer = newbyte[1024]; int len; try {
while ((len mongodbregex= inputStream.read(buffer)) > -1) { byteArrayOutputStream.write(buffer, 0
, len); } byteArrayOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } InputStream byteArrayInputStream =
new ByteArrayInputStream(byteArrayOutputStream.mongodbregextoByteArray()); return byteArrayInputStream; }
@Overridepublic BufferedReader getReader()throws IOException { returnnew BufferedReader(new InputStreamReader(getInputStream())); }
@Overridepublic ServletInputStream getInputStream()throws IOException { final BytemongodbregexArrayInputStream bais =
new ByteArrayInputStream(body); returnnew ServletInputStream() { @Overridepublic
intread()throws IOException { return bais.read(); } @Override
publicbooleanisFinished(){ returnfalse; } @Overridepublicboolean
isReamongodbregexdy(){ returnfalse; } @OverridepublicvoidsetReadListener
(ReadListener readListener){ } }; } }自定義過濾器@Slf4jpublicclass OutRequestFilter
extends OncePerRequestFilter { @SneakyThrows@Overrideprotectedvoid doFilterInternal(ServletRequest smongodbregexervletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException { RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); HttpServletRequest request = (HttpServletRequest) servletRequest;
String requestURL = request.getRequestURI(); log.info("請(qǐng)求mongodbregex路徑:" + requestURL); String method = request.getMethod();
if (!"POST".equals(method)) { thrownew RuntimeException("暫不支持" + method + "請(qǐng)求方式"); }
//獲取請(qǐng)求參數(shù) RequestWrapper requestWrapper = new RequestWrapper(request); String bodyString = requestWrapper.getBodyString()mongodbregex;
if (StringUtils.isEmpty(bodyString)) { thrownew RuntimeException("請(qǐng)求體不能為空"); } log.info(
"請(qǐng)求參數(shù):" + bodyString); JsonRequest jsonRequest = JacksonUtil.jsonToBean(bodyString, JsonRequest.class);
//step0 參數(shù)合法性校驗(yàn)(非空判斷等) parameterValidate(jsonRequest); //stemongodbregexp1 判斷請(qǐng)求合法性1.不允許重復(fù)請(qǐng)求(通過請(qǐng)求唯一id判斷)2.不允許請(qǐng)求時(shí)間與當(dāng)前時(shí)間差距過大(正負(fù)10分鐘)。
long currentTime = System.currentTimeMillis(); long subTime = currentTime - jsonRequest.getTimestamp(); long tenMinuteMs =
10 * 60 * 1000; if (subTime tenMinuteMs) { thrownew RuntimeException(
"請(qǐng)求異常,請(qǐng)求時(shí)間異常"); mongodbregex } String requestUUIDKey = MessageFormat.format(RedisConstant.REQUEST_UUID, jsonRequest.getRequestId());
Object requestFlag = redisUtil.get(requestUUIDKey); if (!StringUtils.isEmpty(requestFlag)) {
thrownew RuntimeException("請(qǐng)求異常,重復(fù)的請(qǐng)求"); } redisUtil.set(requestUUIDmongodbregexKey, JacksonUtil.beanToJson(jsonRequest),
15 * 60); //step2 參數(shù)解密,簽名校驗(yàn),參數(shù)過濾和傳遞 Map paramMap = RSAUtil.bean2Map(jsonRequest); paramMap.remove(
"sign"); //根據(jù)appkey獲取rsa密鑰String appIdKey = MessageFormat.format(RedisConstant.REQUEST_APPID, jsonRequest.getAppId());
Object ob =mongodbregex redisUtil.get(appIdKey); if (StringUtils.isEmpty(ob)) { thrownew RuntimeException(
"找不到指定的appid"); } String jsonString = (String) ob; JSONObject jsonObject = JSONObject.parseObject(jsonString);
//rsa公鑰String publicKey = jsonObject.getString("publicKey"); mongodbregex //rsa私鑰String privateKey = jsonObject.getString(
"privateKey"); //參數(shù)排序 Map sortedMap = RSAUtil.sort(paramMap);
//拼接參數(shù):key1Value1key2Value2String urlParams = RSAUtil.groupStringParam(sortedMap); //簽名驗(yàn)證boolean
verify = RSAUtil.verify(HexUtils.hexStringToBytes(urlParams), publicKmongodbregexey, jsonRequest.getSign());
if (!verify) { thrownew RuntimeException("簽名驗(yàn)證失敗"); } //私鑰解密,獲取aseKeyString
aseKey = RSAUtil.decryptByPrivateKey(HexUtils.hexStringToBytes(jsonRequest.getAseKey()), privateKey);
if (!StringUtils.isEmpty(jsonRequest.getBody())) { // 解密請(qǐng)求報(bào)文Strinmongodbregexg body = "";
try { body = AESUtil.decrypt(jsonRequest.getBody(), aseKey, jsonRequest.getAppId().substring(
16)); } catch (Exception e) { log.error("請(qǐng)求參數(shù)解密異常:",e); throw
new RuntimeException("請(qǐng)求參數(shù)解密異常"); } //報(bào)文傳遞至controller層 requestWrapper.setBodySmongodbregextring(body.getBytes(Charset.forName(
"UTF-8"))); } //將request傳遞下去 filterChain.doFilter(requestWrapper, servletResponse); }
privatevoid parameterValidate(JsonRequest jsonRequest) { if (StringUtils.isEmpty(jsonRequest.getAppId())) {
thrownew RuntimeException("參數(shù)異常,mongodbregexappId不能為空"); } if (StringUtils.isEmpty(jsonRequest.getAseKey())) {
thrownew RuntimeException("參數(shù)異常,aseKey不能為空"); } if (StringUtils.isEmpty(jsonRequest.getRequestId())) {
thrownew RuntimeException("參數(shù)異常,requestId不能為空"); } if (StringUtils.isEmpty(jsonRequemongodbregexst.getSign())) {
thrownew RuntimeException("參數(shù)異常,sign不能為空"); } if (jsonRequest.getTimestamp() == 0l) {
thrownew RuntimeException("參數(shù)異常,timestamp不能為空"); } } }完整流程演示調(diào)用方HttpClientUtils類 public class
HttpClientUtils{ private static Logger logger = Lmongodbregexogger.getLogger(HttpClientUtils.class.getName()); public
staticString doPostJson(String url, String json) { // 創(chuàng)建Httpclient對(duì)象 CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response =
null; String resultString = ""; mongodbregextry { // 創(chuàng)建Http Post請(qǐng)求 HttpPost httpPost =
new HttpPost(url); // 創(chuàng)建請(qǐng)求內(nèi)容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity);
// 執(zhí)行http請(qǐng)求 response = httpClient.execute(httpPost); resultString = EnmongodbregextityUtils.toString(response.getEntity(),
"utf-8"); } catch (Exception e) { resultString = e.getMessage(); logger.info(
"http訪問失?。? + e); } finally { try { response.close(); }
catch (IOException e) { logger.info("response關(guān)閉失?。? + e); mongodbregex } }
return resultString; } /** * post請(qǐng)求,簽名和報(bào)文加密 * * @param url 請(qǐng)求地址 *
@param json 請(qǐng)求json參數(shù) * @param appId 商戶id * @param publicKey rsa公鑰 * @param
privateKey rsa私鑰 * @return */ public staticString mongodbregexdoPostJsonForSign(String url, String json,
String appId, String publicKey, String privateKey) { String aseKey = appId.substring(0, 16); JsonRequest jsonRequest =
new JsonRequest(); jsonRequest.setRequestId(getUUID32()); jsonRequest.setAppId(appId); jsonRequest.smongodbregexetTimestamp(System.currentTimeMillis());
//aseKey 加密 logger.info("開始aseKey加密...."); byte[] enStr = RSAUtil.encryptByPublicKey(aseKey, publicKey);
String aseKeyStr = HexUtils.bytesToHexString(enStr); jsonRequest.setAseKey(aseKeyStr);
//請(qǐng)求參數(shù)進(jìn)行加密String body = ""; try { mongodbregex logger.info("開始請(qǐng)求參數(shù)加密...."); body = AESUtil.encrypt(json, aseKey, appId.substring(
16)); } catch (Exception e) { logger.info("報(bào)文加密異常:" + e); thrownew UncheckedException(
"報(bào)文加密異常", e); } jsonRequest.setBody(body); Map paramMap = RSAUtil.bean2mongodbregexMap(jsonRequest); paramMap.remove(
"sign"); // 參數(shù)排序Map sortedMap = RSAUtil.sort(paramMap); // 拼接參數(shù):key1Value1key2Value2
String urlParams = RSAUtil.groupStringParam(sortedMap); //私鑰簽名 logger.info("開始參數(shù)簽名...."
); String sign = RSAUtil.sign(HexUtils.hexStrinmongodbregexgToBytes(urlParams), privateKey); jsonRequest.setSign(sign);
String requestParams = JacksonUtil.beanToJson(jsonRequest); logger.info("發(fā)起請(qǐng)求....");
String result = doPostJson(url, requestParams); return result; } public staticString
getUUID32() { String uumongodbregexid = UUID.randomUUID().toString(); uuid = uuid.replace("-", ""
); return uuid; } } 需要傳遞的業(yè)務(wù)參數(shù)對(duì)象@DatapublicclassRequestDto{ private String name;
privateint age; private String hobby; }發(fā)送請(qǐng)求publicstaticvoid main(String[] args) { //請(qǐng)mongodbregex求地址String
url = "http://127.0.0.1:8888/test"; RequestDto requestDto = new RequestDto(); requestDto.setAge(
100); requestDto.setName("Longer"); requestDto.setHobby("ball"); String json = JacksonUtil.beanToJson(requestDto);
//appIdString appId = ""; //rsa公鑰mongodbregexString publicKey = ""; //rsa私鑰String privateKey = ""
; HttpClientUtils.doPostJsonForSign(url, json, appId, publicKey, privateKey) }接收方controller
@Slf4j@RestControllerpublicclassTestController{ @RequestMapping("test")public String test(RequestDto requestDto){ lomongodbregexg.info(
"接收到的請(qǐng)求參數(shù)為:"+ JacksonUtil.beanToJson(requestDto)); return"a"; } }因?yàn)槲覀儗?duì)參數(shù)進(jìn)行了統(tǒng)一處理,所以我們的controller接收參數(shù)的對(duì)象是RequestDto對(duì)象,而不是JsonRequest對(duì)象
原鏈接:https://www.jianshu.com/p/9061da5e25d1