最近公司为了项目安全 使用了https 所有接口要使用DES 加密 加密 RequestBody 的value值
心想 这不是很简单吗 直接在拦截器中获取到要上传的数据 然后加密 重新赋值 很简单嘛 但是实践起来 我真的气的想要骂娘 太坑了好吗。。。。无语直接就打到我的脸上
废话不多说 让我重温一下这些坑
第一步 在网络请求类里添加拦截器
在拦截器里对上传的数据进行操作
如果是post 请求 取出来request.body(); 循环 取出 encodedValue 加密后 重新再 addEncoded 添加进去 这里要注意 URLDecoder的解码
如果是get请求 先拿到 request.url() 然后再看这个url中包含不包含请求参数 url.encodedQuery() 如果这个不为空的话 就是接下来字符串截取->修改加密->重新拼接
然后进行网络请求
然后解密 ---->
和后台商量后 后台返回的数据只对 “data” 字段的value进行了加密 好 那我只对“data” 进行解密就好了
获取到 response 对返回的json进行解析 因为后台对“data”进行加密 无疑 data是String类型的 解析解密后 怎么将解密后的data重新安装到json中呢 ?
解密后的data是String类型的 但是原本想要表达的 “data” 该是什么类型呢 不知道什么类型 又该怎么准确的安到实体类里呢
我被这个“data”困阻了 一直在想 怎么直接去操作json串 我知道这也不是一个绝美精妙的办法 但是我脑容量毕竟不大 我觉得我能想到解决的办法已经很棒了 substring(0,1);毕竟 返回的json也就那么几种 { 、[ 、还有什么都没有的
那不就好办了吗 直接统称两类 jsonArray 和jsonObject 至此 我才终于有了完整的思路
我猜看到这里大家也到了耐心的极限了 但是整体的思路 使用的方法 上面已经基本都讲的差不多了 合格的程序员 应该脑海里也知道该怎么做了 有点凡尔赛那味了
上代码!!!!
public class OkhttpInstance {
private static OkHttpClient okHttpClient;
private static Response response;
public static synchronized OkHttpClient createInstance() {
if (okHttpClient == null) {
synchronized (OkhttpInstance.class) {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS) //设置连接超时
.readTimeout(60, TimeUnit.SECONDS) //设置读超时
.writeTimeout(60, TimeUnit.SECONDS) //设置写超时
.retryOnConnectionFailure(true) //是否自动重连
.addInterceptor(interceptor) //添加拦截器
.build();
}
}
}
return okHttpClient;
}
private static Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder requestBuilder = request.newBuilder();
//post请求加密
if (request.body() instanceof FormBody) {
FormBody.Builder newFormBody = new FormBody.Builder();//创建新表单
FormBody oidFormBody = (FormBody) request.body();//请求表单
//循环取出 request Body 注意FormBody 才会有size属性 FormBody可以满足大部分的请求
for (int i = 0; i < oidFormBody.size(); i++) {
String str = oidFormBody.encodedValue(i);//value
String decode = URLDecoder.decode(str);//对value进行URLDecoder解码
String s = oidFormBody.encodedName(i);//name
String name = URLDecoder.decode(s);//对name进行URLDecoder解码 很重要 这两个都加上 不然取出请求体的时候有的请求体被URLDecoder编码 后台不知道你传过去的是什么
String encrypt = DesCipherUtil.encrypt(decode, HDUrl.PAS);//des加密 HDUrl.PAS 是我的密码 你跟后台商量定什么为密码
newFormBody.addEncoded(name.trim(), encrypt.trim());//去空格 相当重要!!都是我踩过的坑
}
requestBuilder.method(request.method(), newFormBody.build());
}
request = requestBuilder.build();
// get请求加密
//还回加密的请求头
HttpUrl url = request.url();
String path = url.encodedPath();//
String query = url.encodedQuery();//请求参数
if (!TextUtils.isEmpty(query)) {
StringBuffer sb = new StringBuffer();
sb.append(HDUrl.DEFAULT).append(path).append("?");//HDUrl.DEFAULT是我的请求地址:https://192.16.2.88 我猜你知道我说的是什么
Set queryList = url.queryParameterNames();
Iterator iterator = queryList.iterator();
for (int i = 0; i < queryList.size(); i++) {
String queryName = iterator.next();
sb.append(queryName).append("=");
String queryKey = url.queryParameter(queryName);
//对query的key进行加密
if (TextUtils.isEmpty(queryKey) || null == queryKey || "null".equals(queryKey) || queryKey.length() == 0 || "".equals(queryKey)) {
} else {
Log.e("tag", "queryKey-----------" + queryKey);
sb.append(DesCipherUtil.encrypt(queryKey, HDUrl.PAS));
}
if (iterator.hasNext()) {
sb.append("&");
}
}
String newUrl = sb.toString();
// 进行加密后的get请求链接
Request.Builder url1 = request.newBuilder()
.url(newUrl);
request = url1.build();
}
response = chain.proceed(request);
byte[] data = response.body().bytes();
String s = new String(data);
MediaType mediaType = response.body().contentType();
try {
Log.e("tag", "s-----------------------" + s);
JSONObject jsonObject = new JSONObject(s);
int code = 0;
if (jsonObject.has("code")) {
code = jsonObject.getInt("code");
} else {
code = jsonObject.getInt("errCode");
}
if (code == 200 || code == 0) {
// 当code=200/0时解密
if (jsonObject.has("data")) {
String code1 = jsonObject.getString("data");
String decrypt = DesCipherUtil.decrypt(code1, HDUrl.PAS);
jsonObject.remove("data");
jsonObject.put("data", decrypt);
Gson gson = new Gson();
//
DefaultBean defaultBean = gson.fromJson(s, DefaultBean.class);
if (decrypt.substring(0, 1).equals("[")) {
List
其实已经很容易看懂了 一些东西我就不做解释了 自己悟去吧 下面贴一下DES加密解密类
private DesCipherUtil() {
throw new AssertionError("No DesCipherUtil instances for you!");
}
static {
// add BC provider
// Security.addProvider(new BouncyCastleProvider());
}
/**
* 加密
*
* @param encryptText 需要加密的信息
* @param key 加密密钥
* @return 加密后Base64编码的字符串
*/
@SuppressLint("NewApi")
public static String encrypt(String encryptText, String key) {
if (encryptText == null || key == null) {
throw new IllegalArgumentException("encryptText or key must not be null");
}
try {
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] bytes = cipher.doFinal(encryptText.getBytes(Charset.forName("UTF-8")));
return Base64.getEncoder().encodeToString(bytes);
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException | NoSuchPaddingException
| BadPaddingException | NoSuchProviderException | IllegalBlockSizeException e) {
throw new RuntimeException("encrypt failed", e);
}
}
/**
* 解密
*
* @param decryptText 需要解密的信息
* @param key 解密密钥,经过Base64编码
* @return 解密后的字符串
*/
public static String decrypt(String decryptText, String key) {
if (decryptText == null || key == null) {
throw new IllegalArgumentException("decryptText or key must not be null");
}
try {
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] bytes = new byte[0];
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
bytes = cipher.doFinal(Base64.getDecoder().decode(decryptText));
}
return new String(bytes, Charset.forName("UTF-8"));
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException | NoSuchPaddingException
| BadPaddingException | NoSuchProviderException | IllegalBlockSizeException e) {
throw new RuntimeException("decrypt failed", e);
}
}
public static void main(String[] args) {
}
这些都是我实实在在用到项目中的 有问题别质疑 我的代码没有问题 傲娇脸