Java Http接口加签、验签操作方法

1、业务背景

最近接触了一些电商业务,发现在处理电商业务接口时,比如淘宝、支付类接口,接口双方为了确保数据参数在传输过程中未经过篡改,都需要对接口数据进行加签,然后在接口服务器端对接口参数进行验签,确保两个签名是一样的,验签通过之后再进行业务逻辑处理。我们这里主要介绍一下处理思路,至于签名算法我不做过多介绍,网上一大堆。

2、处理思路

双方约定好,参数按特定顺序排列,比如按首字母的顺序排列,如url:http://xxx/xxx.do?a=wersd&b=sd2354&c=4&signature=XXXXXXXXXXXX(signature为传入的签名),等你拿到入参后,将参数串a=wersd&b=sd2354&c=4按你们约定的签名规则,自己用md5加签一次,然后和入参的signature值对比,以确认调用者是否合法,这就是接口签名验证的思路。

3、实例练习

接口双方经过沟通,对接口达成如下共识:

1、注意事项,主要指接口的的协议、传入参数类型、签名算法、文件格式等说明

2、下面是一个电商业务接口的真实案例,双方约定好了接口URL、业务参数、固定参数、签名以及返回数据格式

接口调用时,接口调用方代码如下(仅供参考):

package com.pcmall;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class APITest {
  static String TEST_URL = "待定";
  static String TEST_KEY = "待定";
  static String TEST_SEC = "待定";					

  public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String result = getResult(TEST_URL, getReqParam());
    System.out.print(result);
  }					

  private static String getReqParam() throws UnsupportedEncodingException, NoSuchAlgorithmException {
  	TreeMap<String, String> req = new TreeMap<String, String>();
    req.put("a", TEST_KEY);
    req.put("f", "json");
    req.put("l", "zh_CN");
    req.put("m", "zhongan.repair.query");
    req.put("v", "1.0");
    req.put("i", "" + System.currentTimeMillis() / 1000);
    req.put("params", "{\"assignNo\":\"TEST018\"}");
    req.put("s", sign(req, null, TEST_SEC));					

    StringBuilder param = new StringBuilder();
    for (Iterator<Map.Entry<String, String>> it = req.entrySet().iterator(); it.hasNext();) {
      Map.Entry<String, String> e = it.next();
      param.append("&").append(e.getKey()).append("=").append(URLEncoder.encode(e.getValue(), "UTF-8"));
    }					

    return param.toString().substring(1);
  }					

  private static String sign(Map<String, String> paramValues, List<String> ignoreParamNames, String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    StringBuilder sb = new StringBuilder();
    List<String> paramNames = new ArrayList<String>(paramValues.size());
    paramNames.addAll(paramValues.keySet());
    if (ignoreParamNames != null && ignoreParamNames.size() > 0) {
      for (String ignoreParamName : ignoreParamNames) {
        paramNames.remove(ignoreParamName);
      }
    }
    Collections.sort(paramNames);					

    sb.append(secret);
    for (String paramName : paramNames) {
      sb.append(paramName).append(paramValues.get(paramName));
    }
    sb.append(secret);					

    MessageDigest md = MessageDigest.getInstance("SHA-1");
    return byte2hex(md.digest(sb.toString().getBytes("UTF-8")));
  }					

  private static String byte2hex(byte[] bytes) {
    StringBuilder sign = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
      String hex = Integer.toHexString(bytes[i] & 0xFF);
      if (hex.length() == 1) {
        sign.append("0");
      }
      sign.append(hex.toUpperCase());
    }
    return sign.toString();
  }					

  private static String getResult(String urlStr, String content) {
    URL url = null;
    HttpURLConnection connection = null;
    try {
      url = new URL(urlStr);
      connection = (HttpURLConnection) url.openConnection();
      connection.setDoOutput(true);
      connection.setDoInput(true);
      connection.setRequestMethod("POST");
      connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
      connection.setUseCaches(false);
      connection.connect();					

      DataOutputStream out = new DataOutputStream(connection.getOutputStream());
      out.write(content.getBytes("UTF-8"));
      out.flush();
      out.close();					

      BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
      StringBuffer buffer = new StringBuffer();
      String line = "";
      while ((line = reader.readLine()) != null) {
        buffer.append(line);
      }
      reader.close();					

      return buffer.toString();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (connection != null) {
        connection.disconnect();
      }
    }					

    return null;
  }	

}

服务器端代码如下(仅供参考):

@RequestMapping("/repairTakeOrder")
	@ResponseBody
	public ResponseVO repairTakeOrder(@RequestBody String jsonStr) {
		logger.info("repairTakeOrder入参:" + jsonStr);

		ResponseVO responseVO = null;
		try {
			RepairOrder repairOrder = JackJsonUtil.toBean(jsonStr,
					RepairOrder.class);
			TreeMap<String, String> paramsMap = new TreeMap<String, String>();
			paramsMap.put("gsxx01", repairOrder.getGsxx01());
			paramsMap.put("orderType", repairOrder.getOrderType().toString());
			paramsMap.put("serviceNo", repairOrder.getServiceNo());
			paramsMap.put("vipCard", repairOrder.getVipCard());
			paramsMap.put("customerName", repairOrder.getCustomerName());
			paramsMap.put("customerPhone", repairOrder.getCustomerPhone());
			paramsMap.put("customerTel", repairOrder.getCustomerTel());
			paramsMap.put("province", repairOrder.getProvince());
			paramsMap.put("city", repairOrder.getCity());
			paramsMap.put("county", repairOrder.getCounty());
			paramsMap.put("address", repairOrder.getAddress());
			paramsMap.put("salerCode", repairOrder.getSalerCode());
			paramsMap.put("salerName", repairOrder.getSalerName());
			paramsMap.put("storeCode", repairOrder.getStoreCode());
			paramsMap.put("storeName", repairOrder.getStoreName());
			paramsMap.put("site", repairOrder.getSite());

			paramsMap.put("siteDesp", repairOrder.getSiteDesp());
			paramsMap.put("engineerCode", repairOrder.getEngineerCode());
			paramsMap.put("engineerName", repairOrder.getEngineerName());
			if (repairOrder.getServiceDate() != null) {
				paramsMap.put("serviceDate",
						DateUtils.formatDate(repairOrder.getServiceDate()));
			}

			if (repairOrder.getSalePrice() != null) {
				paramsMap.put("salePrice", repairOrder.getSalePrice()
						.toString());
			}

			paramsMap.put("profitCenter", repairOrder.getProfitCenter());
			paramsMap.put("costCenter", repairOrder.getCostCenter());
			paramsMap.put("gsxx02", repairOrder.getGsxx02());
			paramsMap.put("returnReason", repairOrder.getReturnReason());
			if (repairOrder.getOriOrder() != null) {
				paramsMap.put("oriOrder", repairOrder.getOriOrder().toString());
			}

			if (repairOrder.getOriServiceNo() != null) {
				paramsMap.put("oriServiceNo", repairOrder.getOriServiceNo());
			}

			// 拼接签名原串(a=1&b=2)
			String paramSrc = RequestUtils.getParamSrc(paramsMap);
			logger.info("签名原串:" + paramSrc);
			//进行验签操作
			if (SignUtils.verifymd5(paramSrc, repairOrder.getSign())) {
				//处理业务逻辑
				responseVO=erpServiceImpl.repairTakeOrder(repairOrder);

			} else {
				responseVO = new ResponseVO();
				responseVO.setSuccess(false);
				responseVO.setErrorMsg("验签失败");
			}

		} catch (Exception e) {
			logger.error("", e);
			responseVO = new ResponseVO();
			responseVO.setSuccess(false);
			responseVO.setErrorMsg(StringUtils.isNotBlank(e.getMessage()) ? e.getMessage() : "后台异常");
		}
		return responseVO;

	}

以上这篇Java Http接口加签、验签操作方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • php对接java现实加签验签的实例

    我实现的方法,主要是把java生成的密钥转为php能识别的pem格式的密钥,其它的加签.验签采用调用openssl内置签名方法. java生成的密钥主要是字符串:而pem格式密钥是以64位为一行,并且带有如下头和尾的文件格式,然后php再去取得相对应pem格式字符串. pem格式密钥 -----BEGIN PUBLIC KEY----- //64chars一行(多行) -----END PUBLIC KEY----- -----BEGIN RSA PRIVATE KEY----- //64cha

  • Java Http接口加签、验签操作方法

    1.业务背景 最近接触了一些电商业务,发现在处理电商业务接口时,比如淘宝.支付类接口,接口双方为了确保数据参数在传输过程中未经过篡改,都需要对接口数据进行加签,然后在接口服务器端对接口参数进行验签,确保两个签名是一样的,验签通过之后再进行业务逻辑处理.我们这里主要介绍一下处理思路,至于签名算法我不做过多介绍,网上一大堆. 2.处理思路 双方约定好,参数按特定顺序排列,比如按首字母的顺序排列,如url:http://xxx/xxx.do?a=wersd&b=sd2354&c=4&si

  • Nodejs环境Eggjs加签验签示例代码

    加签验签概念 加签: 用Hash函数把原始报文生成报文摘要,然后用私钥对这个摘要进行加密,就得到这个报文对应的数字签名.「注意啦,加签过程要包含一些特殊的私有的东西,比如个人私钥.」 通常来说呢,请求方会把「数字签名和报文原文」一并发送给接收方. 验签: 接收方拿到原始报文和数字签名后,用「同一个Hash函数」从报文中生成摘要A.另外,用对方提供的公钥对数字签名进行解密,得到摘要B,对比A和B是否相同,就可以得知报文有没有被篡改过. 如下使用Egg.js示例代码 // 获取签名 router.p

  • Python3.7基于hashlib和Crypto实现加签验签功能(实例代码)

    环境: Python3.7 依赖库: import datetime import random import requests import hashlib import json import base64 from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from Crypto.Cipher import AES 加签: def si

  • Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签

    Python3.7 基于 pycryptodome 的AES加密解密.RSA加密解密.加签验签,具体代码如下所示: #!/usr/bin/env python # -*- coding: utf8 -*- import os import rsa import json import hashlib import base64 from Crypto.Cipher import AES from ..settings_manager import settings class RSAEncryp

  • Python3加密解密库Crypto的RSA加解密和签名/验签实现方法实例

    关于非对称加密算法我就不过多介绍了,本文着重于python3对RSA算法的实现. from Crypto.PublicKey import RSA import Crypto.Signature.PKCS1_v1_5 as sign_PKCS1_v1_5 #用于签名/验签 from Crypto.Cipher import PKCS1_v1_5 #用于加密 from Crypto import Random from Crypto import Hash x = RSA.generate(204

  • php rsa 加密,解密,签名,验签详解

    php rsa 加密,解密,签名,验签 由于对接第三方机构使用的是Java版本的rsa加解密方法,所有刚开始在网上搜到很多PHP版本的rsa加解密,但是对接java大多都不适用. 以下php版本是适用于对接java接口,java适用密钥再php语言使用是需要添加 -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- 使用密钥: 加密公钥  public_key.cer 解密私钥  private_key.key 签名私钥 sign_key.k

  • 详解NodeJs支付宝移动支付签名及验签

    非常感谢 :http://www.jianshu.com/p/8513e995ff3a?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weibo 的文章,如果不是找到这篇文章我可能还要继续坑几天,代码也基本都是照着他的搬过来的,不过支付宝移动支付文档写的非常糟糕而且没有node的SDK和demo,写起来异常痛苦..好在找到了这篇文章顺便折腾了一下午支付宝的技术人员总算把移动支付整个流程给做

  • python rsa实现数据加密和解密、签名加密和验签功能

    本篇文章主要说明python库rsa生成密钥对,数据的加密解密,api接口的签名和验签,如有抄袭,请留言联系我. 先安装 pip install rsa 安装好后,请看代码 """ 注意: api签名时:签名用私钥,验签用公钥 数据加密时:加密用公钥,解密用私钥 密钥和公钥保存的图片会在下边展示出来 """ import rsa # 对api的签名机制进行验证:签名用私钥,验签用公钥 class RsaEncrypt: def __init__(

  • 浅谈PHP SHA1withRSA加密生成签名及验签

    最近公司对接XX第三方支付平台的代付业务,由于对方公司只有JAVA的demo,所以只能根据文档自己整合PHP的签名加密,网上找过几个方法,踩到各种各样的坑,还好最后算是搞定了,话不多说,代码分享出来. 业务要求:每个签名组装的内容是按字段名的字典顺序升序排序连接的 先组装需要签名的内容: /** * 拼接需要签名的内容 * Author: Tao. * * @param array $data 需签名的字段内容 * * @return string */ public static functi

随机推荐