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、业务参数、固定参数、签名以及返回数据格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
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 ; } } |
服务器端代码如下(仅供参考):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
@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接口加签、验签操作方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
Java Http接口加签、验签操作方法的更多相关文章
- RSA体系 c++/java相互进行加签验签--转
在web开发中,采用RSA公钥密钥体系自制ukey,文件证书登陆时,普遍的做法为:在浏览器端采用c++ activex控件,使用 c++的第三库openssl进行RAS加签操作,在服务器端采用java ...
- Java实现RSA密钥对并在加解密、加签验签中应用的实例
一.项目结构 二.代码具体实现 1.密钥对生成的两种方式:一种生成公钥私文件,一种生成公钥私串 KeyPairGenUtil.java package com.wangjinxiang.genkey. ...
- java RSA 加签验签【转】
引用自: http://blog.csdn.net/wangqiuyun/article/details/42143957/ java RSA 加签验签 package com.testdemo.co ...
- RSA加密解密及RSA加签验签
RSA安全性应用场景说明 在刚接触RSA的时候,会混淆RSA加密解密和RSA加签验签的概念.简单来说加密解密是公钥加密私钥解密,持有公钥(多人持有)可以对数据加密,但是只有持有私钥(一人持有)才可以解 ...
- RSA加密解密与加签验签
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年7月首次在美国公布 ...
- 微信小程序(17)-- RSA加密 解密 加签 验签
RSA加密 解密 加签 验签 /** * 注:区分RSA私钥的类型,有pkcs1和pkcs8.pkcs8格式的私钥主要用于Java中 pkcs1格式: -----BEGIN RSA PRIVATE K ...
- Python rsa公私钥生成 rsa公钥加解密(分段加解密)-私钥加签验签实战
一般现在的SAAS服务提供现在的sdk或api对接服务都涉及到一个身份验证和数据加密的问题.一般现在普遍的做法就是配置使用非对称加密的方式来解决这个问题,你持有SAAS公司的公钥,SAAS公司持有你的 ...
- 支付宝支付集成中:refund_fastpay_by_platform_nopwd接口服务器通知验签不通过
在做p2p配资平台,也就是公司的项目,遇到了一个问题:refund_fastpay_by_platform_nopwd接口服务器通知验签不通过 下面是实录: 通知服务器的POST过来的数据: 1.si ...
- Java使用数字证书加密通信(加解密/加签验签)
本文中使用的Base64Utils.java可参考:http://www.cnblogs.com/shindo/p/6346618.html 证书制作方法可参考:http://www.cnblogs. ...
随机推荐
- Java之使用链表实现队列
import java.util.Iterator; import java.util.NoSuchElementException; /** * 使用链表来实现队列 * 1.考虑结点的结构,包括当前 ...
- 小技巧--tab键自动补齐Git命令
Git是什么,你不清楚? 好吧,那么该篇内容对你也木有帮助,请绕道而行.. 我们在使用Git命令时,可以通过tab键,自动补齐Git,特别是在切换分支时特别有用. 如下,当我们想将当前分支切换到bug ...
- 开源分布式工作流任务调度系统Easy Scheduler Release 1.0.2发布
Easy Scheduler Release 1.0.2===Easy Scheduler 1.0.2是1.x系列中的第三个版本.此版本增加了调度开放接口.worker分组(指定任务运行的机器组).任 ...
- 微信小程序退款 处理类
<?php /** * 微信小程序退款 处理类参考https://www.cnblogs.com/afei-qwerty/p/7922982.html * */ class WeixinRefu ...
- Dockerfile编写注意事项
转载自:https://blog.fundebug.com/2017/05/15/write-excellent-dockerfile/ 一.目标 更快的构建速度 更小的Docker镜像大小 更少的D ...
- Git1:Git简介
目录 什么是版本控制系统 集中式版本控制系统 分布式版本控制系统 Git起源 Git特性 什么是版本控制系统 版本控制系统是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统.版本控制 ...
- windows配置Python多版本共存
windows配置Python多版本共存 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 最近Python开发蛮火的,三年前我的一个运维朋友就告诉我说Python语言将来会很火,当时 ...
- Java基础-字符串连接运算符String link operator
Java基础-字符串连接运算符String link operator 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 字符串链接运算符是通过“+”进行拼接的. 一.使用“+”进行字 ...
- 【转载】C#, VB.NET如何将Excel转换为PDF
在日常工作中,我们经常需要把Excel文档转换为PDF文档.你是否在苦恼如何以C#, VB.NET编程的方式将Excel文档转换为PDF文档呢?你是否查阅了许多资料,运用了大量的代码,但转换后的效果依 ...
- Vue组件穿透
1. element ui怎么修改单独一个label的颜色 用 >>> 进行组件的穿透