圣泉山人 后端开发工程师

API接口签名算法

2018-05-02
PHP

API 安全隐患

目前我们公司接口全部采取的是 HTTP 协议,接口的权限是通过验证 TOKEN 令牌(用户登录成功后,通过用户id参与生成的唯一码)。

存在的隐患:可以通过抓包很容易获取到 TOKEN,此后便可以对系统做很多攻击操作了,比如:恶意数据插入、修改参数等等。

因此,需要对API的请求加上更多安全验证。

这里,计划采用数据签名的方式来防止参数修改。至于其他像恶意数据插入这些安全隐患可以从业务逻辑上防止,就不在这里处理了。

数据签名

对于所有非公开接口请求时,需要增加请求参数:

  • 数据签名 : sign_code
  • 请求时间戳 : req_t

签名算法

数据签名 = 单向散列加密(请求参数 + 请求时间戳 + 私钥)
  • 私钥 :保存在服务端 和 客户端,不进行传输
  • 请求参数 : 全部请求参数(除掉:token)
  • 请求时间戳(req_t) :长度10位(单位:秒),预设过期时间为10秒,也就说每次请求10秒后会过期
  1. 对所有请求参数(除掉:token 以及上传文件的字段,但是包含:req_t)进行字典升序排列;
  2. 将以上排序后的参数列表通过 & 进行字符串连接,如 k1=v1&k2=v2&k3=v3
  3. 对拼接后的字符串转换为全大写形式
  4. 字符串最后通过 _ 拼接上 私钥,得到待加密字符串,比如:k1=v1&k2=v2&k3=v3_fR0%lxkd16E9ACph...
  5. 对字符串进行md5加密

md5

对于PHP 和 java 使用 md5加密结果不一致的问题:由于 java 的加密字符串是 unicode 编码,不受源码文件的编码影响;而PHP的编码是和源码文件的编码一致,受源码编码影响,可以通过如下方式调整java的md5加密方式:

public static String md5(String txt) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(txt.getBytes("UTF-8"));
        StringBuffer buf=new StringBuffer();            
        for(byte b:md.digest()){
            buf.append(String.format("%02x", b&0xff));        
        }
        return  buf.toString();
    } catch ( Exception e ) {
        e.printStackTrace();
        return null;
    } 
}

私钥示例

fR0%lzgd16E923z12phPaoI7MLqqSCr3ojJYij%a^McC2zaff^afaaOBoQCoTONRkjb*CuKzzzsdb$wkpb2T85CfSbcFInF^Hhr

Similar Posts

上一篇 AES算法

Comments