java签名验签,java实现签名验证

  java签名验签,java实现签名验证

  00-1010 1.前言2。签名生成策略3。API签名算法4的Java实现。测试一下。

  00-1010目的:防止中间人攻击。

  场景:

  项目内部的前端和后端调用。在这种场景下,只需要进行常用参数的签名验证和过期请求验证,以防止攻击者劫持请求url后非法请求接口。开放平台向第三方应用程序提供功能。在这种场景下,除了常见的参数验证和请求过期验证,还需要考虑3d应用的授权机制。即使传入了合法参数,未经授权的应用程序也不能请求成功。

  00-1010接下来,将详细描述场景2。其实场景1也包含在场景2里。

  1.例如,请求url:

  http://api.abc.com/a-service/orders?order type=1001 request from=IOs pagenum=2 pagesize=10

  请求参数是:

  参数位置备注例如X-Access-Keyheader客户端授权码,由服务器提供,与accessSecret配对(场景1无此参数)app1X-Access-Tokenheader当前登录用户token d 7 b 5808 c 3 f 443 EB 596225468 c 7 E4 a5x-UtctimeHeader发送请求的时间是2022-2022-02-16t 093:123:43.08 . 3ZX-rand将原始参数设置为stringA,X-Access-Key、X-UTCTime和X-Random固定参数被添加到stringA。stringA中非空参数值和头的参数按照参数名的ASCII码从小到大排序(字典顺序),使用URL键-值对的格式(即key1=value1key2=value2…)拼接成string stringB。

  请注意以下规则:

  参数的ASCII码从小到大排序(字典顺序);如果参数的值为空,则不参与签名;参数区分大小写;验证返回或主动通知签名时,传输的sign参数不参与签名,生成的签名用sign值进行校验。//最终拼接成stringby:order type=1001 x-utc time=2022-02-16t 09:12336043.083 zpagesize=10x-access-key=app 1x-access-token=d7b 5808 C3 f 443 EB 5a 496225468 c 7 E4 a5 pagenu。M=2请求from=iosx-random=341 be 97d 9 aff 90 c 978347 f 66 f 945 b 773。accessSecret在stringB末尾拼接得到stringC字符串,对stringC进行MD5运算得到符号值。

  //最后拼写accessSecret得到StringC:order type=1001 x-utc time=2022-02-16t 09336012:43.083 zpagesize=10x-access-key=app 1x-access-token=d7b 5808 C3 f 443 EB 5a 4962546 8 c 7 E4 a5 pagenum=2 requestfrom=IOSX-Random=341 be 97d 9 aff 90 c 99783477用符号拼接原始请求url,形成最终的请求url。

  http://api.abc.com/a-service/orders?order type=1001 request from=IOs pagenum=2 pagesize=10 sign=0 F5 a3 cc 534961d 129 a 25d 52d 7 ed 8d 003

  5.最终的请求url如下:

  http://api.abc.com/a-service/orders?order type=1001 request from=IOs pagenum=2 pagesize=10 sign=0 F5 a3 cc 534961d 129 a 25d 52d 7 ed 8d 003

  关于参数位置的说明:例如,服务器提供的X-Access-Keyheader客户端授权代码,以及

   accessSecret 配对(场景 1 无此参数)app1X-Access-Tokenheader当前登录用户 tokend7b5808c3f443eb5a496225468c7e4a5X-UTCTimeheader当前发送请求时的时间2022-02-16T09:12:43.083ZX-Randomheader请求随机数341be97d9aff90c9978347f66f945b77orderTypequery订单类型1001requestFromquery订单来源IOSpageNumquery分页参数10pageSizequery分页参数26.服务端 gateway 同样做 sign 签名加密和校验,如果校验不通过则说明请求非法,直接拒绝,通过则下发到业务服务进行正常请求处理。

  

 

  

3. API 签名算法 Java 实现

public class SignUtil { /** * 生成签名 * * @param accessSecret accessSecret * @param url url * @param headers headers * @param body post的body体 * @param <T> body体泛型 * @return sign */ public static <T> String sign(String accessSecret, String url, Map<String, Object> headers, T body) throws IllegalAccessException { Map<String, Object> signMap = new HashMap<>(); if (headers != null) { signMap.putAll(headers); } Map<String, Object> paramMap = getUrlParams(url); if (paramMap != null) { signMap.putAll(paramMap); } Map<String, Object> bodyMap = getBodyParams(body); if (bodyMap != null) { signMap.putAll(bodyMap); } StringBuffer sb = new StringBuffer(); signMap.forEach((k, v) -> { sb.append(k).append("=").append(v).append("&"); }); sb.append("accessSecret=").append(accessSecret); return stringToMD5(sb.toString()); } private static Map<String, Object> getUrlParams(String url) { if (StringUtils.isBlank(url) !url.contains("?")) { return null; } Map<String, Object> paramMap = new HashMap<>(); String params = url.split("\?")[1]; for (String param : params.split("&")) { String[] p = param.split("="); paramMap.put(p[0], p[1]); } return paramMap; } private static <T> Map<String, Object> getBodyParams(T body) throws IllegalAccessException { if (body == null) { return null; } Map<String, Object> bodyMap = new HashMap<>(); for (Field field : body.getClass().getDeclaredFields()) { field.setAccessible(true); bodyMap.put(field.getName(), field.get(body)); } return bodyMap; } private static String stringToMD5(String plainText) { byte[] secretBytes = null; try { secretBytes = MessageDigest.getInstance("md5").digest( plainText.getBytes()); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("没有这个md5算法!"); } return new BigInteger(1, secretBytes).toString(16); }}

 

  

4. 测试一下

public class App { public static void main(String[] args) throws IllegalAccessException { String url = "http://api.abc.com/a-service/orders?orderType=1001&requestFrom=IOS&pageNum=2&pageSize=10"; Map<String, Object> headerMap = new HashMap<>(); headerMap.put("X-Access-Key", "app1"); headerMap.put("X-Access-Token", "d7b5808c3f443eb5a496225468c7e4a5"); headerMap.put("X-UTCTime", generateDate()); headerMap.put("X-Random", "341be97d9aff90c9978347f66f945b77"); BodyVO body = new BodyVO(100000001L, "yangcan", new Date()); String sign = SignUtil.sign("sdfsdfdsfdsfds", url, headerMap, body); System.out.println(sign); } /** * 获取当前时间的UTC格式 */ private static String generateDate() { Date now = new Date(); DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US); return format.format(now); } @Data @AllArgsConstructor public static class BodyVO { private Long ycId; private String ycName; private Date ycTime; }}

输出:

 

  

sign = 4f52eb34b30129a8d511dc803044086b

 

  

到此这篇关于Java实现API sign签名校验的方法详解的文章就介绍到这了,更多相关Java API签名校验内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: