プロジェクトレベルJavaインターフェース署名と検証の実現

17612 ワード

いくつかの項目では、クライアントは、サービスのインターフェースを呼び出す際に、通常、クライアントの認証を保証するために署名検証を設定する必要がある.署名の過程では、一般的に各会社は自分の署名規則と署名アルゴリズムを持っています.広く使用されているのは非対称暗号化アルゴリズムRSAを中心として、クライアントで秘密鍵を使ってパラメータを暗号化して鍵を生成し、サーバーに転送してから、この鍵を公開鍵で解読します.復号された文字列パラメータはクライアントから送られてきたパラメータと比較されます.同じ場合、認証に成功します.
まとめると、
  • クライアント         -   最初にすべてのパラメータを取得し、並べ替えを行い、文字列を生成します.             -   この文字列MD 5を暗号化して大文字にします.             -   その後、秘密鍵を使ってMD 5を再暗号化し、最終的な署名signを生成する.             -   この署名signをサービス端末
  • に渡す.
  • サービス端末         -   すべてのパラメータを取得             -   パラメータに署名したsignパラメータを削除して並べ替えて文字列を生成します.             -   この文字列MD 5を暗号化して大文字にします.             -   公開鍵を用いてsign文字列を解読して一つのStringを取得し、そして第3ステップで取得した文字列と比較して、等しい場合には認証に成功する
  • .
    以上の規則により、クライアントの署名とサービスの検証を行います.
    クライアント署名
    例えば私達のこれは私達のurlです.
    http://localhost:8080/task/test?name=  &age=8&timestamp=1591261543133
    
    
    
    urlには名前、年齢、タイムスタンプの三つのパラメータがあります.まず、これらのパラメータを並べ替えます.
      public static String getSortedContent(Map<String, String> data) {
        StringBuffer content = new StringBuffer();
        List<String> keys = new ArrayList<String>(data.keySet());
        Collections.sort(keys);
        int index = 0;
        for (String key : keys) {
          String value = data.get(key);
          content.append((index == 0 ? "" : "&")).append(key).append("=").append(value);
          index++;
        }
        return content.toString();
      }
    
    
    並べ替えられた文字列を暗号化して大文字にします.
    String summary = DigestUtils.md5Hex(data).toLowerCase();
    
    
    
    最後にsummaryを秘密鍵で暗号化します.
        public static String EncryptByRSAPriKey(String content,String priKey) throws Exception {
            try {
                PrivateKey privateKey = SecurityUtil.getRSAPriKey(priKey);
                Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
                cipher.init(Cipher.ENCRYPT_MODE, privateKey);
                cipher.update(content.getBytes(SecurityUtil.RSA_CHARSET));
                return SecurityUtil.encodeBase64(cipher.doFinal());
            } catch (Exception e) {
                e.printStackTrace();
                throw new Exception();
            }
        }
    
    
    最終的に私達が欲しいsignを得て、サービスに伝えます.
    実務上の検証
    まずすべてのパラメータを取得したら、signを除去し、残りのパラメータを並べ替え、MD 5を暗号化し、大文字にします.
      /**
       *
       * @param params   sign     
       * @param sign
       * @param pubKey   
       * @return
       * @throws ApiError
       */
      public static boolean verifySign( Map<String, String> params,String sign,String pubKey) throws ApiError {
        if (StringUtil.isEmpty(sign)) {
          return false;
        }
        String signType = params.get(Constants.FN_SIGN_TYPE);;//     RSA   
        if (StringUtil.isEmpty(signType) || !signType.equals(Constants.SIGN_TYPE_RSA)) {
          return false;
        }
        //       
        String data = ApiUtils.getSortedContent(params);
        ApiLogger.getLogger().debug("sign data:" + data);
        String summary = DigestUtils.md5Hex(data).toLowerCase();
        ApiLogger.getLogger().debug("sign summary:" + summary);
    ​
        String summaryDecode = null;
        try {
          summaryDecode = SecurityUtil.DecryptByRSAPubKey(sign, pubKey);
        } catch (Exception e) {
          throw new ApiError("do_digest_error", e);
        }
        return summary.equals(summaryDecode);
      }
    
    
    SecurityUtil.DecryptByRSAPubKey(sign、pbKey)の方法は以下の通りです.
        /**
         *
         *   :      RSA      
         * @author wangbing
         * @since
         * @param content        
         * @param pubKey   
         * @return       
         * @throws Exception
         */
        public static String DecryptByRSAPubKey(String content, String pubKey){
            try {
                PublicKey publicKey = SecurityUtil.getRSAPubKey(priKey);
                Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
                cipher.init(Cipher.DECRYPT_MODE, publicKey);
                cipher.update(SecurityUtil.decodeBase64(content));
                return new String(cipher.doFinal(), SecurityUtil.RSA_CHARSET);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
    これで、業務の核心コードが完成します.
    WeChatは白黒の色を探して私に注目してください.