乐趣区

关于java:Java接口签名Signature实现方案

Java 接口签名 (Signature) 实现计划

大家好,我是程序员田同学!

今天上午收到一个需要,针对以后的零碎开发一个对外开放的接口。

既然是对外开放,那么调用者肯定没有咱们零碎的 Token,就须要对调用者进行签名验证,签名验证采纳支流的验证形式,采纳 Signature 的形式。

一、要求

下图为具体要求

二、流程

​ 1、线下调配 appid 和 appsecret,针对不同的调用方调配不同的 appid 和 appsecret

2、退出timestamp(工夫戳),10 分钟内数据无效

3、退出流水号noncestr(避免反复提交),至多为 10 位。针对查问接口,流水号只用于日志落地,便于前期日志核查。针对办理类接口需校验流水号在有效期内的唯一性,以防止反复申请。

4、退出signature,所有数据的签名信息。

三、实现

简略来说,调用者调用接口业务参数在 body 中传递,header 中额定减少四个参数 signature、appkey、timestamp、noncestr。

咱们在后盾取到四个参数,其后三个参数加上调用者调配的 appSecret,应用字典排序并应用 MD5 加密后与第一个参数 signature 进行比对,统一既示意调用者有权限调用。

以下代码为接口验证签名的 demo 实现:

   // 援用 jackson 依赖
    @Autowired
    private ObjectMapper objectMapper;

    @Value("${appsecret}")
    private String appSecret;
  
  /**
     * 验证签名
     * @param preInfoItem
     * @return
     */
    boolean checkSignature(PreInfoItem preInfoItem) throws JsonProcessingException, IllegalAccessException {

        String signature="signature";

        String appkey="appkey";

        String timestamp="timestamp";

        String noncestr="noncestr";

        HttpServletRequest request = ServletUtils.getRequest();

        String headerSignature = request.getHeader(signature);
        String headerAppkey = request.getHeader(appkey);
        String headerTimestamp = request.getHeader(timestamp);
        String headerNoncestr = request.getHeader(noncestr);

        // 因为须要排序,间接应用 TreeMap
        Map<String,Object> parms=new TreeMap<>();
        parms.put(appkey,headerAppkey);
        parms.put(timestamp,headerTimestamp);
        parms.put(noncestr,headerNoncestr);


        Map<String, Object> stringObjectMap = objectToMap(parms, preInfoItem);
        String s = buildSignature(stringObjectMap);
        // 签名比对
        if (s.equals(headerSignature)){return true;}
        return false;
    }

    Map<String,Object> objectToMap(Map<String,Object> map,Object o){Field[] declaredFields = o.getClass().getDeclaredFields();

        for (Field field : declaredFields) {field.setAccessible(true);

            try {if (field.getName() instanceof String){map.put(field.getName(),field.get(o));
                }
            }catch (IllegalAccessException e){throw new CustomException("对象转 map 异样");
            }

        }
        return map;
    }

  private String buildSignature(Map<String,Object> maps){
      String s2;
      try {
            StringBuffer s = null;
            String s1 = objectMapper.writeValueAsString(maps);
            // 增加 appSecret
            s.append(s1).append(appSecret);
             s2 = DigestUtils.md5DigestAsHex(s.toString().getBytes());
        }catch (JsonProcessingException e){throw new CustomException("map 转 json 异样");
        }

        return s2;
    }

好啦,赶快去试一下吧!

退出移动版