Java接口簽名(Signature)實現方案


Java接口簽名(Signature)實現方案

大家好,我是程序員田同學!

今天上午收到一個需求,針對當前的系統開發一個對外開放的接口。

既然是對外開放,那么調用者一定沒有我們系統的Token,就需要對調用者進行簽名驗證,簽名驗證采用主流的驗證方式,采用Signature 的方式。

一、要求

下圖為具體要求

image-20220118171527945

二、流程

​ 1、線下分配appid和appsecret,針對不同的調用方分配不同的appid和appsecret

  2、加入timestamp(時間戳),10分鍾內數據有效

  3、加入流水號noncestr(防止重復提交),至少為10位。針對查詢接口,流水號只用於日志落地,便於后期日志核查。 針對辦理類接口需校驗流水號在有效期內的唯一性,以避免重復請求。

  4、加入signature,所有數據的簽名信息。

image-20220118171245456

三、實現

簡單來說,調用者調用接口業務參數在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;
    }

好啦,趕快去試一下吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM