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接口加签、验签操作方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小牛知识库。
$ git tag 添加-n选项,就可以显示标签的注解。 建立标签 $ git tag <tagname> 建立含批注的标签 $ git tag -a <tagname> 删除标签 $ git tag -d <tagname>
本文向大家介绍php接口数据加密、解密、验证签名,包括了php接口数据加密、解密、验证签名的使用技巧和注意事项,需要的朋友参考一下 代码很简单,这里就不多废话了,直接奉上代码 以上就是本文所述的全部内容了,希望本代码能给大家学习php加密解密能够带来些帮助。
作用 开发密钥用于加强开发商对账户的控制,用来验证开发商软件与平台账户是否同属于一个开发商。如果不是在自己平台下面建立的账户将无法使用。 产品开发时,直接将gpid和密钥固定写入代码中,以达到产品与开发商账号的绑定。 开发商密钥可以生成多个,可以一个产品对应一个gpid,以方便灵活的控制。并且gpid可以在后台启用/禁用,方便客户端产品的升级管理。 签名加强方法 1.请求参数中增加一个gpid 2
主要内容:创建标签,查看标签,删除标签标签操作允许为存储库中的特定版本提供有意义的名称。 假设项目中有两个程序员:和,他们决定标记项目代码,以便以后可以更容易访问这些代码。 创建标签 使用命令来标记当前指针。在创建标签时需要提供选项的标签名称,并提供带选项的标签消息。 如果要标记特定提交,则使用相应的而不是指针。使用以下命令将标签推送到远程存储库。 查看标签 假设开发人员()创建了标签。 现在,另外一个开发人员()就可以使用带有选项的
主要为数据模型提供了一些增删查改的接口,以及事务的处理,锁表等一些便捷操作。 //查询列表 public function getList($sql); //添加数据 public function add($data); //替换数据 public function replace($data); //删除指定id的数据 public function delete($id); //批量
上节我们讲了 buffer。本节我们就讲解下图中剩下的两个重点——分屏、标签。 1. 分屏 分屏顾名思义就是同时显示多个窗口。其他编辑器中也会有这个功能。 分屏方式: 垂直: vim -On [FILE_1] [FILE_2] … 水平: vim -on [FILE_1] [FILE_2] … 1.1 分屏操作 指令 含义 ctrl+w c/q 关闭当前窗口/最后一个窗口时退 ctrl+w s 上