需求如下,提供远程调用的借口,参数加密。
直接上代码
des加密算法代码:
package com.ruisitech.bi.util;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
/**
* 类 名 称:AESEncryptTools
* 类 描 述:DES加密解密算法
*/
public final class DESEncryptTools {
static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(DESEncryptTools.class);
//加密算是des
private static final String ALGORITHM = "DES";
//转换格式
private static final String TRANSFORMATION = "DES/ECB/PKCS5Padding";
private static String key = "134xmkd766";
//利用8个字节64位的key给src加密
public static byte[] encrypt(byte[] src) {
try {
//加密
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
KeySpec keySpec = new DESKeySpec(key.getBytes());
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
secureRandom.setSeed(key.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKey, secureRandom);
byte[] enMsgBytes = cipher.doFinal(src);
return enMsgBytes;
} catch (Exception e) {
e.printStackTrace();
logger.info(e);
}
return null;
}
//利用8个字节64位的key给src解密
public static byte[] decrypt(byte[] encryptBytes){
try {
Cipher deCipher = Cipher.getInstance(TRANSFORMATION);
SecretKeyFactory deDecretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
KeySpec deKeySpec = new DESKeySpec(key.getBytes());
SecretKey deSecretKey = deDecretKeyFactory.generateSecret(deKeySpec);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
secureRandom.setSeed(key.getBytes());
deCipher.init(Cipher.DECRYPT_MODE, deSecretKey, secureRandom);
byte[] deMsgBytes = deCipher.doFinal(encryptBytes);
return deMsgBytes;
} catch (Exception e) {
e.printStackTrace();
logger.info(e);
}
return null;
}
public static void main(String[] args) throws Exception{
String msg = "123";
System.out.println("加密前:"+msg);
byte[] encryptBytes = DESEncryptTools.encrypt(msg.getBytes());
System.out.println("加密后:"+new String(encryptBytes));
byte[] deMsgBytes = DESEncryptTools.decrypt(encryptBytes);
System.out.println("解密后:"+new String(deMsgBytes));
}
}
响应端代码
package com.ruisitech.bi.web.custombi;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.misc.BASE64Decoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
/**
* @author:mazhen
* @date:2018/12/6 17:48:
* @description: 后台数据筛选功能对应控制器
*/
@Controller
@RequestMapping(value = "/userFilter")
public class UserFilterController {
static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(UserFilterController.class);
@RequestMapping(value="/queryBossWithUid.action", method = RequestMethod.POST)
// 此时方法默认为 get方式
// @RequestMapping(value="/queryBossWithUid.action")
public @ResponseBody
Object saveRhQueryCondition1(HttpServletRequest req, HttpServletResponse res) {
String uid = req.getParameter(UserFilterConstants.TYPE_UID);
BASE64Decoder base64decoder = new BASE64Decoder();
try {
byte[] encodeByte = base64decoder.decodeBuffer(uid);
uid = new String(DESEncryptTools.decrypt(encodeByte));
} catch (IOException e) {
e.printStackTrace();
logger.info(e);
}
//这里进行具体的业务处理并返回
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put("status","UP");
String str = JSONObject.toJSON(hashMap).toString();
return str;
}
}
客户端请求
package com.ruisitech.bi.util;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import sun.misc.BASE64Encoder;
/**
* @author:mazhen
* @date:2018/12/28 14:17:
* @description:
*/
public class HttpClientUtil {
public static void main(String[] args) {
// 请求接口地址
String url = "http://localhost:8080/rsbi/userFilter/queryBossWithUid.action";
// String url = "http://localhost:8080/rsbi/alarm/updateAlarmCountResultTxtNum.action";
// 请求参数
String uid = "123";
HttpClient httpclient = null;
PostMethod post = null;
GetMethod get = null;
try {
//创建连接
httpclient = new HttpClient();
// post方式
post = new PostMethod(url);
// 设置编码方式
post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
System.out.println(new String(DESEncryptTools.encrypt(uid.getBytes())));
// 不编解码的话,请求端加密后在是服务端无法将解密
BASE64Encoder base64encoder = new BASE64Encoder();
String encode=base64encoder.encode(DESEncryptTools.encrypt(uid.getBytes()));
// 添加参数
post.addParameter("uid", encode);
// post.addParameter("uid", new String(DESEncryptTools.encrypt(uid.getBytes())));
// 执行请求
int i = httpclient.executeMethod(post);
// 接口返回信息
String info = new String(post.getResponseBody(), "UTF-8");
// get方式
// // 因为加密后的字符问题,会报异常,如java.lang.IllegalArgumentException:
// // Invalid uri 'http://localhost:8080/rsbi/userFilter/queryBossWithUid.action?uid=[B@65fb9ffc': Invalid query
// get = new GetMethod(url+"?uid="+DESEncryptTools.encrypt(uid.getBytes()));
// // 设置编码方式
// get.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
get.
// // 添加参数
get.addParameter("uid", uid);
// // 执行请求
// int i = httpclient.executeMethod(get);
// // 接口返回信息
// String info = new String(get.getResponseBody(), "UTF-8");
System.out.println(info);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭连接,释放资源
post.releaseConnection();
((SimpleHttpConnectionManager) httpclient.getHttpConnectionManager()).shutdown();
}
}
}
现在分享下开发过程中遇到的问题:
1对传参加密后导致get方式接口无法调用,就是编码后导致url中会有各种特殊字符
对uid加密后报错如下:
java.lang.IllegalArgumentException: Invalid uri 'http://localhost:8080/rsbi/userFilter/queryBossWithUid.action?uid=[B@65fb9ffc': Invalid query
解决方案:将post修改为get方式,在方法上增加method = RequestMethod.POST
2请求端加密后在是服务端无法将加密
//报错如下:
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
原因一
SecureRandom 实现完全隨操作系统本身的內部狀態,除非調用方在調用 getInstance 方法之後又調用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系统上则不同。
原因二:
1、加密完byte[] 后,需要将加密了的byte[] 转换成base64保存,如:
BASE64Encoder base64encoder = new BASE64Encoder();
String encode=base64encoder.encode(bytes);
2、解密前,需要将加密后的字符串从base64转回来再解密,如:
BASE64Decoder base64decoder = new BASE64Decoder();
byte[] encodeByte = base64decoder.decodeBuffer(str);