欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)API sign簽名校驗(yàn)的方法詳解

 更新時(shí)間:2022年07月12日 11:00:38   作者:TopDuang  
為了防止中間人攻擊,有時(shí)我們需要進(jìn)行API sign 簽名校驗(yàn)。本文將用Java語(yǔ)言實(shí)現(xiàn)API sign 簽名校驗(yàn),感興趣的小伙伴可以嘗試一下

1. 前言

目的:為防止中間人攻擊。

場(chǎng)景:

  • 項(xiàng)目?jī)?nèi)部前后端調(diào)用,這種場(chǎng)景只需要做普通參數(shù)的簽名校驗(yàn)和過期請(qǐng)求校驗(yàn),目的是為了防止攻擊者劫持請(qǐng)求 url 后非法請(qǐng)求接口。
  • 開放平臺(tái)向第三方應(yīng)用提供能力,這種場(chǎng)景除了普通參數(shù)校驗(yàn)和請(qǐng)求過期校驗(yàn)外,還要考慮 3d 應(yīng)用的授權(quán)機(jī)制,不被授權(quán)的應(yīng)用就算傳入了合法的參數(shù)也不能被允許請(qǐng)求成功。

2. 簽名生成策略

接下來詳述場(chǎng)景 2,其實(shí)場(chǎng)景 1 也包含在場(chǎng)景 2 內(nèi)部。

1.舉例請(qǐng)求 url:

http://api.abc.com/a-service/orders?orderType=1001&requestFrom=IOS&pageNum=2&pageSize=10

請(qǐng)求參數(shù)為:

參數(shù)名位置備注舉例
X-Access-Keyheader客戶端授權(quán)碼,服務(wù)端提供,和 accessSecret 配對(duì)(場(chǎng)景 1 無(wú)此參數(shù))app1
X-Access-Tokenheader當(dāng)前登錄用戶 tokend7b5808c3f443eb5a496225468c7e4a5
X-UTCTimeheader當(dāng)前發(fā)送請(qǐng)求時(shí)的時(shí)間2022-02-16T09:12:43.083Z
X-Randomheader請(qǐng)求隨機(jī)數(shù)341be97d9aff90c9978347f66f945b77
orderTypequery訂單類型1001
requestFromquery訂單來源IOS
pageNumquery分頁(yè)參數(shù)10
pageSizequery分頁(yè)參數(shù)2

2.設(shè)原始參數(shù)為 stringA,stringA 中添加 X-Access-Key、X-UTCTime、X-Random 固定參數(shù),將 stringA 內(nèi)非空參數(shù)值和 header 的參數(shù)按照參數(shù)名 ASCII 碼從小到大排序(字典序),使用 URL 鍵值對(duì)的格式(即 key1=value1&key2=value2…)拼接成字符串 stringB。

注意如下規(guī)則:

  • 參數(shù)名 ASCII 碼從小到大排序(字典序);
  • 如果參數(shù)的值為空不參與簽名;
  • 參數(shù)名區(qū)分大小寫;
  • 驗(yàn)證調(diào)用返回或主動(dòng)通知簽名時(shí),傳送的 sign 參數(shù)不參與簽名,將生成的簽名與該 sign 值作校驗(yàn)。
// 最終拼接為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 字符串,并對(duì) stringC 進(jìn)行 MD5 運(yùn)算,得到 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加密得到最終簽名結(jié)果sign:
sign=e1a4907ef03adee3fa8d395552814f4e

4.將原始的請(qǐng)求 url 拼接上 sign 形成最終的請(qǐng)求 url。

http://api.abc.com/a-service/orders?orderType=1001&requestFrom=IOS&pageNum=2&pageSize=10&sign=0f5a3cc534961d129a25d52d7ed8d003

5.最終請(qǐng)求 url 如下:

http://api.abc.com/a-service/orders?orderType=1001&requestFrom=IOS&pageNum=2&pageSize=10&sign=0f5a3cc534961d129a25d52d7ed8d003

參數(shù)名位置備注舉例
X-Access-Keyheader客戶端授權(quán)碼,服務(wù)端提供,和 accessSecret 配對(duì)(場(chǎng)景 1 無(wú)此參數(shù))app1
X-Access-Tokenheader當(dāng)前登錄用戶 tokend7b5808c3f443eb5a496225468c7e4a5
X-UTCTimeheader當(dāng)前發(fā)送請(qǐng)求時(shí)的時(shí)間2022-02-16T09:12:43.083Z
X-Randomheader請(qǐng)求隨機(jī)數(shù)341be97d9aff90c9978347f66f945b77
orderTypequery訂單類型1001
requestFromquery訂單來源IOS
pageNumquery分頁(yè)參數(shù)10
pageSizequery分頁(yè)參數(shù)2

6.服務(wù)端 gateway 同樣做 sign 簽名加密和校驗(yàn),如果校驗(yàn)不通過則說明請(qǐng)求非法,直接拒絕,通過則下發(fā)到業(yè)務(wù)服務(wù)進(jìn)行正常請(qǐng)求處理。

3. API 簽名算法 Java 實(shí)現(xiàn)

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("沒有這個(gè)md5算法!");
        }

        return new BigInteger(1, secretBytes).toString(16);
    }
}

4. 測(cè)試一下

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);
    }

    /**
     * 獲取當(dāng)前時(shí)間的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

到此這篇關(guān)于Java實(shí)現(xiàn)API sign簽名校驗(yàn)的方法詳解的文章就介紹到這了,更多相關(guān)Java API簽名校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis-Plus 修改和添加自動(dòng)填充時(shí)間方式

    MyBatis-Plus 修改和添加自動(dòng)填充時(shí)間方式

    這篇文章主要介紹了MyBatis-Plus 修改和添加自動(dòng)填充時(shí)間方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Mac系統(tǒng)搭建JDK及JMETER過程解析

    Mac系統(tǒng)搭建JDK及JMETER過程解析

    這篇文章主要介紹了Mac系統(tǒng)搭建JDK及JMETER過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 如何在 Java 中實(shí)現(xiàn)一個(gè) redis 緩存服務(wù)

    如何在 Java 中實(shí)現(xiàn)一個(gè) redis 緩存服務(wù)

    為什么要使用緩存?說到底是為了提高系統(tǒng)的運(yùn)行速度。將用戶頻繁訪問的內(nèi)容存放在離用戶最近,訪問速度最快的地方,提高用戶的響應(yīng)速度。下面我們來一起深入學(xué)習(xí)一下吧
    2019-06-06
  • SpringBoot利用切面注解及反射實(shí)現(xiàn)事件監(jiān)聽功能

    SpringBoot利用切面注解及反射實(shí)現(xiàn)事件監(jiān)聽功能

    這篇文章主要介紹了springboot事件監(jiān)聽,通過利用切面、注解、反射實(shí)現(xiàn),接下來將對(duì)這幾種方式逐一說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助
    2022-07-07
  • java 工廠模式的實(shí)例詳解

    java 工廠模式的實(shí)例詳解

    這篇文章主要介紹了java 工廠模式的實(shí)例詳解的相關(guān)資料,這里舉例說明該如何實(shí)現(xiàn)工廠模式,需要的朋友可以參考下
    2017-09-09
  • linux重啟java服務(wù)的腳本

    linux重啟java服務(wù)的腳本

    這篇文章主要介紹了linux重啟java服務(wù)的腳本,本文分步驟通過shell腳本給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • SpringMVC空指針異常NullPointerException解決及原理解析

    SpringMVC空指針異常NullPointerException解決及原理解析

    這篇文章主要介紹了SpringMVC空指針異常NullPointerException解決及原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java?@Autowired報(bào)錯(cuò)原因分析和4種解決方案

    Java?@Autowired報(bào)錯(cuò)原因分析和4種解決方案

    這篇文章主要介紹了Java?@Autowired報(bào)錯(cuò)原因分析和4種解決方案,文章圍繞主題展開詳細(xì)內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考以一下
    2022-05-05
  • SpringBoot Shiro授權(quán)實(shí)現(xiàn)過程解析

    SpringBoot Shiro授權(quán)實(shí)現(xiàn)過程解析

    這篇文章主要介紹了SpringBoot Shiro授權(quán)實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • java對(duì)接微信小程序詳細(xì)流程(登錄&獲取用戶信息)

    java對(duì)接微信小程序詳細(xì)流程(登錄&獲取用戶信息)

    這篇文章主要給大家介紹了關(guān)于java對(duì)接微信小程序(登錄&獲取用戶信息)的相關(guān)資料,我們?cè)陂_發(fā)微信小程序時(shí)經(jīng)常需要獲取用戶微信用戶名以及頭像信息,微信提供了專門的接口API用于返回這些信息,需要的朋友可以參考下
    2023-08-08

最新評(píng)論