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 map = GsonUtils.getGson().fromJson(object, new TypeToken>() { // }.getType()); // final Uri.Builder builder = new Uri.Builder(); // List 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 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; } } /** * 基本类型加密 *

* 判断当前值是否需要参与签名,保持跟云端一致 * 空字符串不参与 * 数组,集合不参与 * * @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")); } }