当前位置: 首页 > 工具软件 > HTTP Sign > 使用案例 >

http接口签名机制

卢勇
2023-12-01

Java开发中,经常会有与第三方接口对接的情况。为了提高对接中数据传输的安全性,防止请求参数被篡改,通常都需要增加签名sign。比如支付接口,依照双方事先约定好的规则,请求方对数据进行加签,接口提供方则对签名进行验证,验证通过才能放行,进行后续的业务逻辑处理。

 这里最重要的就是签名规则,将参数按照一定顺序排列,添加密钥,然后加密,得到sign

1、对请求参数加密。此处是以get请求链接为例,以hashmap默认的排序,前后加上密钥,以MD5的形式,进行加密,获得sign,然后拼接在url之后。

/**
 * 跳转链接地址加密
 * @param taskUrl
 * @return
 * @throws Exception
 */
public String dingAuth(String taskUrl) throws Exception {
    if (Assert.isEmpty(secret)) {
        throw new BusinessException("密钥为空");
    }
    URL url = new URL(taskUrl);
    String query = url.getQuery();
    //此处处理很繁琐,主要是保持参数顺序
    String[] arrs = query.split("&");
    Map<String, Object> map = new HashMap<>();
    for(String arr : arrs){
        map.put(arr.substring(0, arr.indexOf("=")), arr.substring(arr.indexOf("=")+1));
    }
    StringBuilder sb = new StringBuilder(secret);
    map.forEach((k, v) -> {
        //为空的不参与加密
        if(!StringUtils.isEmpty(v)){
            sb.append(k).append("=").append(v).append("&");
        }
    });
    sb.delete(sb.length()-1, sb.length());
    sb.append(secret);
    //MD5加密
    String encryValue = DigestUtils.md5DigestAsHex(sb.toString().getBytes());
    taskUrl = taskUrl + "&sign=" + encryValue;

    return taskUrl;
}

2、对请求进行验签。其实验签和加签的原理相同。请求地址中剥离出sign,然后将剩余的参数按照加签同样的规则进行加密,加密结果与之前的sign作比较,如果一致则验证通过。

/**
 * 请求签名验证
 * @param queryParams
 */
public void auth(Map<String, Object> queryParams) {
    String sign = (String) queryParams.get("sign");
    if (StringUtils.isEmpty(sign)) {
        throw new BusinessException("非法参数");
    }
    if (Assert.isEmpty(secret)) {
        throw new BusinessException("密钥为空");
    }
    // sign不参与签名
    queryParams.remove("sign");
    Map<String, Object> map = new TreeMap<String, Object>(queryParams);
    StringBuilder strBuilder = new StringBuilder(secret);
    map.forEach((k, v) -> {
        if(v != null){
            strBuilder.append(k).append("=").append(v).append("&");
        }
    });
    strBuilder.delete(strBuilder.length()-1, strBuilder.length());
    strBuilder.append(secret);
    //MD5加密
    String encryValue = DigestUtils.md5DigestAsHex(strBuilder.toString().getBytes());
    if (!sign.equals(encryValue)) {
        throw new BusinessException("签名错误");
    }
}

值得一提的是,签名机制仅能确保请求中的参数不被篡改,并不能保证传输中敏感数据的安全性。

 类似资料: