APP URL签名验证的实现API防篡改

原创 ImWiki  2020-07-17 07:11  阅读 160 次
摘要:

Android 网络安全:URL签名验证的实现API防篡改

我们在做APP开发的时候,APP的网络安全是极其重要,我们有必要对请求的API进行加密和防篡改。HTTPS是一个很好的传输加密的方式。如果APP的请求API地址和参数被泄露,我们还是可能会被恶意请求。

所以我们有必要实现 URL签名,对请求的参数进行校验,在客户端生成URL签名,在服务端对签名进行校验,如果客户端的URL签名算法保密做得好,就可以避免非法请求,签名算法的加密需要使用 C++编写,这里就不介绍,只介绍URL签名算法的实现。

原理

在 APP 端,对请求的参数+时间戳+密钥,进行MD5生成一个值,并和时间戳、参数一起传到服务器,在服务器也进行相同的方式生成一个MD5,对比两个MD5是否一致,如果一致就说明这个请求是从APP发起的,否则就是非法请求。

算法

算法的实现有很多方式,这里介绍一个比较通用的算法。假设参与参数签名计算的请求参数分别是“k1”、“k2”、“k3”,它们的值分别是“v1”、“v2”、“v3”,则参数签名计算方法如下:

  1. 每一个请求都必须带有timestamp参数,长度为10的时间戳;
  2. 将请求参数格式化为“key=value”格式,即“k1=v1”、“k2=v2”、“k3=v3”;
  3. 将格式化好的参数键值对以字典序升序排列后,拼接在一起,即“k1=v1k2=v2k3=v3”;
  4. 在拼接好的字符串末尾追加上一个密钥(需要注意保密,保存在服务端和客户端);
  5. 对上述字符串进行MD5,即为签名的值,并在。
  6. 在 HTTP Header 增加字段 sign,传递上述的MD5值。
服务器验证
  1. 对所有接收到的参数也以上面的方式拼接,并加上密钥生成MD5;
  2. 取出 Header中的 sign 字段进行对比。如果一样就说明没有被篡改,如果不一样就返回错误;
  3. 对参数中的 timestamp 字段和服务器的时间进行对比,如果误差超过 5分钟就说明请求已经过期,就应该返回错误。
代码

/**
 * 签名生成算法
 * @param HashMap<String,String> params 请求参数集,所有参数必须已转换为字符串类型
 * @param String secret 签名密钥
 * @return 签名
 * @throws IOException
 */
public static String getSignature(HashMap<String,String> params, String secret) throws IOException
{
    // 先将参数以其参数名的字典序升序进行排序
    Map<String, String> sortedParams = new TreeMap<String, String>(params);
    Set<Entry<String, String>> entrys = sortedParams.entrySet();
 
    // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起
    StringBuilder basestring = new StringBuilder();
    for (Entry<String, String> param : entrys) {
        basestring.append(param.getKey()).append("=").append(param.getValue());
    }
    basestring.append(secret);
 
    // 使用MD5对待签名串求签
    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输出的二进制结果转换为小写的十六进制
    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();
}

 

本文地址:https://www.dandroid.cn/?p=7120
关注我们:请关注一下我们的今日头条号:扫描二维码到桌源码网的头条号,头条号:大安卓源码
版权声明:本文为原创文章,版权归 ImWiki 所有,欢迎分享本文,转载请保留出处!
NEXT:已经是最新一篇了

发表评论


表情