<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
目的:為防止中間人攻擊。
場景:
接下來詳述場景 2,其實場景 1 也包含在場景 2 內部。
1.舉例請求 url:
http://api.abc.com/a-service/orders?orderType=1001&requestFrom=IOS&pageNum=2&pageSize=10
請求引數為:
引數名 | 位置 | 備註 | 舉例 |
---|---|---|---|
X-Access-Key | header | 使用者端授權碼,伺服器端提供,和 accessSecret 配對(場景 1 無此引數) | app1 |
X-Access-Token | header | 當前登入使用者 token | d7b5808c3f443eb5a496225468c7e4a5 |
X-UTCTime | header | 當前傳送請求時的時間 | 2022-02-16T09:12:43.083Z |
X-Random | header | 請求亂數 | 341be97d9aff90c9978347f66f945b77 |
orderType | query | 訂單型別 | 1001 |
requestFrom | query | 訂單來源 | IOS |
pageNum | query | 分頁引數 | 10 |
pageSize | query | 分頁引數 | 2 |
2.設原始引數為 stringA,stringA 中新增 X-Access-Key、X-UTCTime、X-Random 固定引數,將 stringA 內非空引數值和 header 的引數按照引數名 ASCII 碼從小到大排序(字典序),使用 URL 鍵值對的格式(即 key1=value1&key2=value2…)拼接成字串 stringB。
注意如下規則:
// 最終拼接為stringB: orderType=1001X-UTCTime=2022-02-16T09:12:43.083ZpageSize=10X-Access-Key=app1X-Access-Token=d7b5808c3f443eb5a496225468c7e4a5pageNum=2requestFrom=IOSX-Random=341be97d9aff90c9978347f66f945b77
3.在 stringB 最後拼接上 accessSecret (金鑰) 得到 stringC 字串,並對 stringC 進行 MD5 運算,得到 sign 值。
// 最後拼上accessSecret得到stringC: orderType=1001X-UTCTime=2022-02-16T09:12:43.083ZpageSize=10X-Access-Key=app1X-Access-Token=d7b5808c3f443eb5a496225468c7e4a5pageNum=2requestFrom=IOSX-Random=341be97d9aff90c9978347f66f945b77&accessSecret=192006250b4c09247ec02edce69f6a2d // md5加密得到最終簽名結果sign: sign=e1a4907ef03adee3fa8d395552814f4e
4.將原始的請求 url 拼接上 sign 形成最終的請求 url。
http://api.abc.com/a-service/orders?orderType=1001&requestFrom=IOS&pageNum=2&pageSize=10&sign=0f5a3cc534961d129a25d52d7ed8d003
5.最終請求 url 如下:
http://api.abc.com/a-service/orders?orderType=1001&requestFrom=IOS&pageNum=2&pageSize=10&sign=0f5a3cc534961d129a25d52d7ed8d003
引數名 | 位置 | 備註 | 舉例 |
---|---|---|---|
X-Access-Key | header | 使用者端授權碼,伺服器端提供,和 accessSecret 配對(場景 1 無此引數) | app1 |
X-Access-Token | header | 當前登入使用者 token | d7b5808c3f443eb5a496225468c7e4a5 |
X-UTCTime | header | 當前傳送請求時的時間 | 2022-02-16T09:12:43.083Z |
X-Random | header | 請求亂數 | 341be97d9aff90c9978347f66f945b77 |
orderType | query | 訂單型別 | 1001 |
requestFrom | query | 訂單來源 | IOS |
pageNum | query | 分頁引數 | 10 |
pageSize | query | 分頁引數 | 2 |
6.伺服器端 gateway 同樣做 sign 簽名加密和校驗,如果校驗不通過則說明請求非法,直接拒絕,通過則下發到業務服務進行正常請求處理。
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); } }
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簽名校驗內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45