API 安全隐患
目前我们公司接口全部采取的是 HTTP 协议,接口的权限是通过验证 TOKEN 令牌(用户登录成功后,通过用户id参与生成的唯一码)。
存在的隐患:可以通过抓包很容易获取到 TOKEN,此后便可以对系统做很多攻击操作了,比如:恶意数据插入、修改参数等等。
因此,需要对API的请求加上更多安全验证。
这里,计划采用数据签名的方式来防止参数修改。至于其他像恶意数据插入这些安全隐患可以从业务逻辑上防止,就不在这里处理了。
数据签名
对于所有非公开接口请求时,需要增加请求参数:
- 数据签名 :
sign_code
- 请求时间戳 :
req_t
签名算法
数据签名 = 单向散列加密(请求参数 + 请求时间戳 + 私钥)
- 私钥 :保存在服务端 和 客户端,不进行传输
- 请求参数 : 全部请求参数(除掉:
token
) - 请求时间戳(
req_t
) :长度10位(单位:秒),预设过期时间为10秒,也就说每次请求10秒后会过期
- 对所有请求参数(除掉:
token
以及上传文件的字段,但是包含:req_t
)进行字典升序排列; - 将以上排序后的参数列表通过
&
进行字符串连接,如k1=v1&k2=v2&k3=v3
- 对拼接后的字符串转换为全大写形式
- 字符串最后通过
_
拼接上 私钥,得到待加密字符串,比如:k1=v1&k2=v2&k3=v3_fR0%lxkd16E9ACph...
- 对字符串进行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