package com.hdl.linkpm.sdk.core.interceptor;
|
|
import android.net.Uri;
|
import android.text.TextUtils;
|
|
import androidx.annotation.NonNull;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.google.gson.JsonElement;
|
import com.google.gson.JsonObject;
|
import com.google.gson.JsonParser;
|
import com.google.gson.reflect.TypeToken;
|
import com.hdl.hdlhttp.utils.GsonConvert;
|
import com.hdl.linkpm.sdk.HDLLinkPMSdk;
|
import com.hdl.linkpm.sdk.core.interceptor.HDLSmartHeader;
|
import com.hdl.linkpm.sdk.template.GsonUtils;
|
import com.hdl.linkpm.sdk.utils.HDLMD5Utils;
|
import com.hdl.linkpm.sdk.utils.HDLSDKLog;
|
|
import java.io.IOException;
|
import java.io.UnsupportedEncodingException;
|
import java.net.URLDecoder;
|
import java.nio.charset.Charset;
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.Map;
|
|
import okhttp3.FormBody;
|
import okhttp3.Headers;
|
import okhttp3.Interceptor;
|
import okhttp3.MediaType;
|
import okhttp3.Request;
|
import okhttp3.RequestBody;
|
import okhttp3.Response;
|
import okio.Buffer;
|
|
/**
|
* Created by Tong on 2021/11/4.
|
* 加密并自动补充参数,appKey、timestamp
|
* 只支持表单、json
|
* 最终json方式提交
|
*/
|
public class HDLEncryptInterceptor implements Interceptor {
|
|
|
@NonNull
|
@Override
|
public Response intercept(@NonNull Chain chain) throws IOException {
|
Request request = chain.request();
|
Headers headers = request.headers();
|
if (!isIgnoreSignHeader(headers)) {
|
return chain.proceed(encrypt(request));
|
}
|
|
return chain.proceed(request);
|
}
|
|
|
/**
|
* 添加sign字段
|
*/
|
private Request encrypt(Request request) {
|
final String timestamp = String.valueOf(System.currentTimeMillis());
|
final String appKey = HDLLinkPMSdk.getAppKey();
|
final String appSecret = HDLLinkPMSdk.getAppSecret();
|
final JsonObject json = getBodyJson(request);
|
if (json != null) {
|
json.addProperty("appKey", appKey);
|
json.addProperty("timestamp", timestamp);
|
json.addProperty("sign", getSign(json, appSecret));
|
final RequestBody requestBody = RequestBody.create(json.toString(), MediaType.parse("application/json;charset=UTF-8"));
|
return request.newBuilder().post(requestBody)
|
.build();
|
}
|
return request;
|
}
|
|
|
/**
|
* 是否忽略自定义的加密头
|
*/
|
private boolean isIgnoreSignHeader(Headers headers) {
|
String signHeader = headers.get(HDLSmartHeader.IGNORE_SIGN_HEADER);
|
|
return !TextUtils.isEmpty(signHeader);
|
}
|
|
private JsonObject getBodyJson(Request request) {
|
|
RequestBody body = request.body();
|
if (body instanceof FormBody) {
|
JsonObject object = new JsonObject();
|
FormBody formBody = (FormBody) body;
|
for (int i = 0; i < formBody.size(); i++) {
|
object.addProperty(formBody.encodedName(i), formBody.value(i));
|
}
|
return object;
|
} else {
|
//json格式
|
try {
|
String bodyString = getBodyString(request);
|
if (!TextUtils.isEmpty(bodyString)) {
|
final JsonElement parseString = JsonParser.parseString(bodyString);
|
return parseString.getAsJsonObject();
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
|
}
|
return null;
|
}
|
|
private String getBodyString(Request request) {
|
try {
|
RequestBody body = request.body();
|
if (body != null) {
|
Buffer buffer = new Buffer();
|
body.writeTo(buffer);
|
Charset charset = Charset.forName("UTF-8");
|
MediaType contentType = body.contentType();
|
charset = contentType.charset(charset);
|
return buffer.readString(charset);
|
}
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
return "";
|
}
|
|
|
/**
|
* 需要按字母排序
|
*
|
* @param json 所有字段使用urlParameter拼接,除了appSecret
|
*/
|
private String getSign(JsonObject json, String appSecret) {
|
String builder = jsonToUrlParameter(json) +
|
appSecret;
|
return HDLMD5Utils.encodeMD5(builder);
|
}
|
|
|
private String jsonToUrlParameter(JsonObject object) {
|
// final Map<String, String> map = GsonUtils.getGson().fromJson(object, new TypeToken<Map<String, String>>() {
|
// }.getType());
|
// final Uri.Builder builder = new Uri.Builder();
|
// List<String> list = new ArrayList<>(map.keySet());
|
// Collections.sort(list);
|
// for (String key : list) {
|
// String value = map.get(key);
|
// if (valueNeedSign(value)) {
|
// builder.appendQueryParameter(key, value);
|
// }
|
// }
|
// return builder.build().getQuery();
|
final Uri.Builder builder = new Uri.Builder();
|
try {
|
JSONObject jsonobject = JSON.parseObject(object.toString());
|
List<String> list = new ArrayList<>(jsonobject.keySet());
|
Collections.sort(list);
|
for (String key : list) {
|
Object obj = jsonobject.get(key);
|
if (isSignValue(obj))
|
builder.appendQueryParameter(key, obj.toString());
|
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return builder.build().getQuery();
|
}
|
|
private static boolean isSignValue(Object value) {
|
if (value == null) return false;
|
if (value instanceof Number) return true;
|
String className = value.getClass().getSimpleName();
|
switch (className) {
|
case "String":
|
case "Integer":
|
case "Boolean":
|
case "Long":
|
case "Short":
|
case "Float":
|
case "Double":
|
case "Character":
|
case "Byte":
|
if (TextUtils.isEmpty(value.toString())) return false;
|
return true;
|
default:
|
return false;
|
|
}
|
|
}
|
|
|
/**
|
* 基本类型加密
|
* <p>
|
* 判断当前值是否需要参与签名,保持跟云端一致
|
* 空字符串不参与
|
* 数组,集合不参与
|
*
|
* @return ture 需要加密
|
*/
|
private static boolean valueNeedSign(String valueStr) {
|
try {
|
if (!TextUtils.isEmpty(valueStr)) {
|
JsonElement json = JsonParser.parseString(valueStr);
|
if (json != null && (json.isJsonPrimitive() || json.getAsJsonPrimitive().isString())) {
|
return true;
|
}
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
return false;
|
}
|
|
public static boolean isPrimitive(String type) {
|
return (type.equals("char")
|
|| type.equals("double") || type.equals("float")
|
|| type.equals("integer") || type.equals("string")
|
|| type.equals("boolean")) || (type.equals("Char")
|
|| type.equals("Double") || type.equals("Float")
|
|| type.equals("Integer") || type.equals("String")
|
|| type.equals("Boolean") || type.equals("int")
|
|| type.equals("long") || type.equals("Int") || type
|
.equals("Long"));
|
}
|
|
}
|