Android 網(wǎng)絡(luò)安全:URL簽名驗(yàn)證的實(shí)現(xiàn)API防篡改

我們?cè)谧鯝PP開發(fā)的時(shí)候,APP的網(wǎng)絡(luò)安全是極其重要,我們有必要對(duì)請(qǐng)求的API進(jìn)行加密和防篡改。HTTPS是一個(gè)很好的傳輸加密的方式。如果APP的請(qǐng)求API地址和參數(shù)被泄露,我們還是可能會(huì)被惡意請(qǐng)求。

所以我們有必要實(shí)現(xiàn) URL簽名,對(duì)請(qǐng)求的參數(shù)進(jìn)行校驗(yàn),在客戶端生成URL簽名,在服務(wù)端對(duì)簽名進(jìn)行校驗(yàn),如果客戶端的URL簽名算法保密做得好,就可以避免非法請(qǐng)求,簽名算法的加密需要使用 C++編寫,這里就不介紹,只介紹URL簽名算法的實(shí)現(xiàn)。

原理

在 APP 端,對(duì)請(qǐng)求的參數(shù)+時(shí)間戳+密鑰,進(jìn)行MD5生成一個(gè)值,并和時(shí)間戳、參數(shù)一起傳到服務(wù)器,在服務(wù)器也進(jìn)行相同的方式生成一個(gè)MD5,對(duì)比兩個(gè)MD5是否一致,如果一致就說明這個(gè)請(qǐng)求是從APP發(fā)起的,否則就是非法請(qǐng)求。

算法

算法的實(shí)現(xiàn)有很多方式,這里介紹一個(gè)比較通用的算法。假設(shè)參與參數(shù)簽名計(jì)算的請(qǐng)求參數(shù)分別是“k1”、“k2”、“k3”,它們的值分別是“v1”、“v2”、“v3”,則參數(shù)簽名計(jì)算方法如下:

  1. 每一個(gè)請(qǐng)求都必須帶有timestamp參數(shù),長(zhǎng)度為10的時(shí)間戳;
  2. 將請(qǐng)求參數(shù)格式化為“key=value”格式,即“k1=v1”、“k2=v2”、“k3=v3”;
  3. 將格式化好的參數(shù)鍵值對(duì)以字典序升序排列后,拼接在一起,即“k1=v1k2=v2k3=v3”;
  4. 在拼接好的字符串末尾追加上一個(gè)密鑰(需要注意保密,保存在服務(wù)端和客戶端);
  5. 對(duì)上述字符串進(jìn)行MD5,即為簽名的值,并在。
  6. 在 HTTP Header 增加字段 sign,傳遞上述的MD5值。
服務(wù)器驗(yàn)證
  1. 對(duì)所有接收到的參數(shù)也以上面的方式拼接,并加上密鑰生成MD5;
  2. 取出 Header中的 sign 字段進(jìn)行對(duì)比。如果一樣就說明沒有被篡改,如果不一樣就返回錯(cuò)誤;
  3. 對(duì)參數(shù)中的 timestamp 字段和服務(wù)器的時(shí)間進(jìn)行對(duì)比,如果誤差超過 5分鐘就說明請(qǐng)求已經(jīng)過期,就應(yīng)該返回錯(cuò)誤。
  4. 生成的簽名需要臨時(shí)保存校驗(yàn),不允許URL重復(fù)請(qǐng)求。
代碼
/**
 * 簽名生成算法
 * @param HashMap<String,String> params 請(qǐng)求參數(shù)集,所有參數(shù)必須已轉(zhuǎn)換為字符串類型
 * @param String secret 簽名密鑰
 * @return 簽名
 * @throws IOException
 */
public static String getSignature(HashMap<String,String> params, String secret) throws IOException
{
    // 先將參數(shù)以其參數(shù)名的字典序升序進(jìn)行排序
    Map<String, String> sortedParams = new TreeMap<String, String>(params);
    Set<Entry<String, String>> entrys = sortedParams.entrySet();
 
    // 遍歷排序后的字典,將所有參數(shù)按"key=value"格式拼接在一起
    StringBuilder basestring = new StringBuilder();
    for (Entry<String, String> param : entrys) {
        basestring.append(param.getKey()).append("=").append(param.getValue());
    }
    basestring.append(secret);
 
    // 使用MD5對(duì)待簽名串求簽
    byte[] bytes = null;
    try {
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        bytes = md5.digest(basestring.toString().getBytes("UTF-8"));
    } catch (GeneralSecurityException ex) {
        throw new IOException(ex);
    }
 
    // 將MD5輸出的二進(jìn)制結(jié)果轉(zhuǎn)換為小寫的十六進(jìn)制
    StringBuilder sign = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(bytes[i] & 0xFF);
        if (hex.length() == 1) {
            sign.append("0");
        }
        sign.append(hex);
    }
    return sign.toString();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 12,309評(píng)論 6 13
  • 寫在前面:加密和簽名是兩回事,加密的目的是防止信息泄露,簽名的目的是防止篡改和偽造 MD5、SHA-1、SHA-2...
    望穿天堂閱讀 15,796評(píng)論 0 6
  • 這里先簡(jiǎn)單介紹單向散列函數(shù)、消息摘要和哈希碰撞的的概念 單向散列函數(shù): 將任意長(zhǎng)度的信息轉(zhuǎn)換為較短的固定長(zhǎng)度的值,...
    坤_7a1e閱讀 3,645評(píng)論 0 0
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,621評(píng)論 1 32
  • 七個(gè)月29天 布丁的活動(dòng)量特別大。 現(xiàn)在天也特別熱。 媽媽的瞌睡也特別多。
    hs雙兒閱讀 128評(píng)論 0 0

友情鏈接更多精彩內(nèi)容