From 817ddb3b34c32c150361e5237a8f1614897bef59 Mon Sep 17 00:00:00 2001 From: dimengzhe Date: Mon, 9 Dec 2024 23:10:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yxt/ss/gateway/api/rest/Signature.java | 215 +++++++++--------- .../ss/gateway/api/utils/AppKeyConfig.java | 26 +++ .../ss/gateway/api/utils/SignatureQuery.java | 8 +- .../ss/gateway/api/utils/SignatureUtil.java | 9 +- src/main/resources/application-devv.yml | 5 + src/main/resources/application.yml | 6 + 6 files changed, 153 insertions(+), 116 deletions(-) create mode 100644 src/main/java/com/yxt/ss/gateway/api/utils/AppKeyConfig.java diff --git a/src/main/java/com/yxt/ss/gateway/api/rest/Signature.java b/src/main/java/com/yxt/ss/gateway/api/rest/Signature.java index 7c79adb..85b946c 100644 --- a/src/main/java/com/yxt/ss/gateway/api/rest/Signature.java +++ b/src/main/java/com/yxt/ss/gateway/api/rest/Signature.java @@ -1,9 +1,11 @@ package com.yxt.ss.gateway.api.rest; -import com.yxt.ss.gateway.api.utils.ResultBean; -import com.yxt.ss.gateway.api.utils.SignatureQuery; -import com.yxt.ss.gateway.api.utils.SignatureUtil; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yxt.ss.gateway.api.utils.*; import okhttp3.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -15,6 +17,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.time.Instant; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; @@ -29,26 +32,42 @@ import java.util.concurrent.TimeUnit; @RequestMapping("/signature") public class Signature { + @Autowired + private AppKeyConfig appKeyConfig; + + public String getSecret(String appKey) { + return appKeyConfig.getKeys().get(appKey); + } + + //appkey - static final String APPKEY = "appkey"; + static final String APPKEY = "appKey4"; //secret static final String SECRET = "secret"; - //获取签名 + //获取参数 @PostMapping("/getSign") - ResultBean getSign(SignatureQuery query) { + ResultBean getSign(SignatureQuery query) { ResultBean rb = ResultBean.fireFail(); try { - Map formData = new HashMap<>(); -// Map map = query.getParameters(); -// formData.put("key1", map.getOrDefault("key1", "").toString()); - formData = query.getParameters(); - String appKey = query.getAppKey(); - String secret = query.getSecret(); - + Map formData = query.getParameters(); + Map tree = new TreeMap<>(formData); + tree.put("_app", APPKEY); + tree.put("_t", String.valueOf(System.currentTimeMillis() / 1000)); + tree.put("_s", ""); // 生成签名 - String sign = SignatureUtil.generateSignature(formData, appKey, secret); - return rb.success().setData(sign); + String sign = SignatureUtil.generateSignature(tree, SECRET); + //添加签名值map + tree.put("_sign", sign); + //发起请求 + ResultBean resultBean = client(tree); + if (!resultBean.getSuccess()) { + return rb.setMsg(resultBean.getMsg()); + } + //通过验证继续调用接口 + + + return rb.success(); } catch (UnsupportedEncodingException e) { return rb.setMsg("Unsupported encoding: " + e.getMessage()); } catch (NoSuchAlgorithmException e) { @@ -56,7 +75,71 @@ public class Signature { } } - public static void main(String[] args) { + //验证 + @PostMapping("/validate") + ResultBean validate(Map data) { + ResultBean rb = ResultBean.fireFail(); + Map parameters = data; + //1、解析参数,校验_app是否正确,_t是否在5分钟内。 + if (!parameters.containsKey("_app") || + parameters.get("_app") == null || + parameters.get("_app").trim().isEmpty()) { + return rb.setMsg("_app参数缺失或无效"); + } + //2、根据_app参数获取对应的secret值。 + String secret = getSecret(parameters.get("_app")); + if (StringUtils.isEmpty(secret)) { + return rb.setMsg("_app参数不正确"); + } + if (parameters.containsKey("_t") || + parameters.get("_t") == null || + parameters.get("_t").trim().isEmpty()) { + return rb.setMsg("_t参数缺失"); + } + + String _t = parameters.get("_t"); + // 获取当前的秒级时间戳 + long currentTimestamp = Instant.now().getEpochSecond(); + // 将字符串转换为 long 类型 + long timestamp = Long.parseLong(_t); + // 计算时间差,允许最大偏差 5 分钟(300秒) + long timeDifference = Math.abs(currentTimestamp - timestamp); + + if (timeDifference > 300) { + return rb.setMsg("时间已超过5分钟,时间失效"); + } + String _sign = parameters.get("_sign"); + //3、检验签名,成功则继续调用接口,失败返回失败信息。 + parameters.remove("_sign"); + try { + // 3.1. 重新生成签名 + String calculatedSignature = SignatureUtil.generateSignature(parameters, secret); + + // 3.2. 使用固定时间比较方式验证签名 + boolean valid = MessageDigest.isEqual( + calculatedSignature.getBytes("UTF-8"), + _sign.getBytes("UTF-8") + ); + if (!valid) { + return rb.setMsg("签名不正确"); + } + + } catch (UnsupportedEncodingException e) { + return rb.setMsg("Encoding error: " + e.getMessage()); + } catch (NoSuchAlgorithmException e) { + return rb.setMsg("Algorithm error: " + e.getMessage()); + } catch (Exception e) { + return rb.setMsg("Unexpected error: " + e.getMessage()); + } + + + return rb.success(); + + + } + + public ResultBean client(Map data) { + ResultBean rb = ResultBean.fireFail(); OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) @@ -66,14 +149,7 @@ public class Signature { try { // 构建URL String endPoint = "http://127.0.0.1:9999"; - String path = "/signature/getSign"; - - // 假设data是一个包含所有参数的字典 - Map data = new HashMap<>(); - data.put("parameters[key1]", "value1"); - data.put("parameters[key2]", "value2"); - data.put("appKey", "testAppKey"); - data.put("secret", "testSecret"); + String path = "/signature/validate"; // 创建FormData FormBody.Builder formBuilder = new FormBody.Builder(); @@ -94,93 +170,28 @@ public class Signature { // 发送请求 try (Response response = client.newCall(request).execute()) { + String responseBody = response.body().string(); + // 使用 Jackson 解析 JSON 响应 + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(responseBody); + String success = jsonNode.path("success").asText(); + String msg = jsonNode.path("msg").asText(); + if ("false".equals(success)) { + return rb.setMsg(msg); + } if (response.isSuccessful()) { System.out.println("Response: " + response.body().string()); } else { - System.err.println("Request failed: " + response.code()); + System.err.println("Request failed: " + response.message()); } + + } } catch (IOException e) { System.err.println("Network error: " + e.getMessage()); } catch (Exception e) { System.err.println("Unexpected error: " + e.getMessage()); } + return rb.success(); } - - - /** - * 对传入的参数集合进行签名处理 - * 返回系统参数 - */ - @PostMapping("/getSignParameters") - public ResultBean> signParameters(SignatureQuery query) { - ResultBean> rb = ResultBean.fireFail(); - - try { - Map parameters = query.getParameters(); - - // 2. 使用 TreeMap 按照字典顺序对参数进行排序 - Map tree = new TreeMap<>(parameters); - tree.put("_app", query.getAppKey()); - tree.putIfAbsent("_t", String.valueOf(System.currentTimeMillis())); - - // 3. 拼接参数串 - String content = SignatureUtil.joinParameters(tree); - - // 4. 将参数串前后拼接密钥 - content = query.getSecret() + content + query.getSecret(); - - // 5. 计算 sign 值 - String sign = SignatureUtil.md5(content); - - // 6. 添加系统参数 - tree.put("_sign", sign); - tree.put("_s", ""); - - return rb.success().setData(tree); - - } catch (UnsupportedEncodingException e) { - return rb.setMsg("Encoding error: " + e.getMessage()); - } catch (NoSuchAlgorithmException e) { - return rb.setMsg("Algorithm error: " + e.getMessage()); - } catch (Exception e) { - return rb.setMsg("Unexpected error: " + e.getMessage()); - } - } - - /** - * 验证签名是否正确 - * - * @return 是否验证通过 - */ - @PostMapping("/validateSignature") - public ResultBean validateSignature(SignatureQuery query) { - ResultBean rb = ResultBean.fireFail(); - - try { - Map parameters = query.getParameters(); - String appKey = query.getAppKey(); - String secret = query.getSecret(); - - - // 2. 重新生成签名 - String calculatedSignature = SignatureUtil.generateSignature(parameters, appKey, secret); - - // 3. 使用固定时间比较方式验证签名 - boolean valid = MessageDigest.isEqual( - calculatedSignature.getBytes("UTF-8"), - query.getReceivedSignature().getBytes("UTF-8") - ); - - return rb.success().setData(valid); - } catch (UnsupportedEncodingException e) { - return rb.setMsg("Encoding error: " + e.getMessage()); - } catch (NoSuchAlgorithmException e) { - return rb.setMsg("Algorithm error: " + e.getMessage()); - } catch (Exception e) { - return rb.setMsg("Unexpected error: " + e.getMessage()); - } - } - - } diff --git a/src/main/java/com/yxt/ss/gateway/api/utils/AppKeyConfig.java b/src/main/java/com/yxt/ss/gateway/api/utils/AppKeyConfig.java new file mode 100644 index 0000000..bb8a6b5 --- /dev/null +++ b/src/main/java/com/yxt/ss/gateway/api/utils/AppKeyConfig.java @@ -0,0 +1,26 @@ +package com.yxt.ss.gateway.api.utils; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @description: + * @author: dimengzhe + * @date: 2024/12/9 + **/ +@Component +@ConfigurationProperties(prefix = "app.keys") +public class AppKeyConfig { + + private Map keys; + + public Map getKeys() { + return keys; + } + + public void setKeys(Map keys) { + this.keys = keys; + } +} diff --git a/src/main/java/com/yxt/ss/gateway/api/utils/SignatureQuery.java b/src/main/java/com/yxt/ss/gateway/api/utils/SignatureQuery.java index 5f374e6..6a26073 100644 --- a/src/main/java/com/yxt/ss/gateway/api/utils/SignatureQuery.java +++ b/src/main/java/com/yxt/ss/gateway/api/utils/SignatureQuery.java @@ -13,13 +13,7 @@ import java.util.Map; @Data public class SignatureQuery { - private String appKey; - - private String secret; - - //业务参数 + //传入的参数 private Map parameters = new HashMap<>(); - //原签名值 - private String receivedSignature; } diff --git a/src/main/java/com/yxt/ss/gateway/api/utils/SignatureUtil.java b/src/main/java/com/yxt/ss/gateway/api/utils/SignatureUtil.java index add06c4..3c71acc 100644 --- a/src/main/java/com/yxt/ss/gateway/api/utils/SignatureUtil.java +++ b/src/main/java/com/yxt/ss/gateway/api/utils/SignatureUtil.java @@ -19,18 +19,13 @@ public class SignatureUtil { * 生成请求签名 * * @param parameters 请求参数 - * @param appKey 应用的 AppKey * @param secret 密钥 * @return 签名 */ - public static String generateSignature(Map parameters, String appKey, String secret) throws UnsupportedEncodingException, NoSuchAlgorithmException { - // 1. 使用 TreeMap 按照字典顺序对参数进行排序 - Map sortedParams = new TreeMap<>(parameters); - sortedParams.put("_app", appKey); // 添加应用的 AppKey - sortedParams.put("_t", String.valueOf(System.currentTimeMillis())); // 添加时间戳 + public static String generateSignature(Map parameters, String secret) throws UnsupportedEncodingException, NoSuchAlgorithmException { // 2. 拼接参数字符串 - String content = joinParameters(sortedParams); + String content = joinParameters(parameters); // 3. 将密钥加在参数字符串的前后 content = secret + content + secret; diff --git a/src/main/resources/application-devv.yml b/src/main/resources/application-devv.yml index e69de29..f79e9c6 100644 --- a/src/main/resources/application-devv.yml +++ b/src/main/resources/application-devv.yml @@ -0,0 +1,5 @@ +app: + keys: + appKey1: secret1 + appKey2: secret2 + appKey3: secret3 \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fb2d262..a08d670 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,3 +6,9 @@ spring: profiles: active: devv +logging: + level: + org: + springframework: + context: DEBUG +