本文demo下载地址:http://www.wisdomdd.cn/Wisdom/resource/articleDetail.htm?resourceId=1135
【概述】
本文基于webservice技术实现平台架构, 此架构用于提供平台服务,服务可以用于客户的对接以达到服务客户的目的,并且保证服务过程中的通讯数据是安全的, 类似于 支付宝的支付服务,商家可以申请相应的帐号和私密信息,用于完成支付操作并且保障信息的不可篡改, 但支付宝是通过RSA来校验数据的安全性,而本文是使用md5来校验数据, 客户端与服务端的通讯使用webservice, 以https形式进行交互, 本文假定你已经对axis的webservice的机制和使用有一定的了解
【流程】
1. 客户向平台服务申请AppID(axcpud123)和AppKeySecret(124jfj3ff3AjifLLefl)
2. 客户准备数据, 数据内容为 telPhone=15261873121, userId=000001, idCert=32132219871234232
AppID+ & + (用户数据内容按照key名称从小到大排序) + & + AppKeySecret
对上面的数据进行MD5进行加密码,生成密文 sign
3. 以axis webservice向服务端发送服务, 服务方法名 为serverMethod
url_wsdl: https://域名/工程名/webservice名称?wsdl
@Override
public String ysSignUrl(){
StringBuilder sb=new StringBuilder();
try{
String time=getTimeStr();
TestDTO data = new TestDTO();
data .setAppId(AppId);
data .setTime(time);
data .setTelPhone(phone);
data .setUserId(userId);
data .setIdCert(idCert);
String j=JSON.toJSONString(data,true);
JSONObject json=JSONObject.fromObject(j);
String sortJson=commUtil.getSortStr(json,Constants.REGX);
sb.append(sortJson).append(Constants.REGX).append(data.getAppSecretKey());
String sign=Md5Util.getMd5(sb.toString());
sb.setLength(0);
sb.append(data.getYsUrl()).append(url_wsdl);
Service service = new Service();
Call call=(Call)service.createCall();
call.setTargetEndpointAddress(new java.net.URL(sb.toString()));
call.setOperationName(new QName("http://wsdl.com/", "serverMethod"));
call.addParameter("appId", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("time", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("sign", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("telPhone", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("userId", XMLType.XSD_STRING, ParameterMode.IN);
call.addParameter("idCert", XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
String result = call.invoke(new Object[] { data.getAppId(),time, sign,
data.getTelPhone(), data.getUserId(), data.getIdCert()
}).toString();
}catch(ServiceException se ){
}catch(MalformedURLException me){
}catch(RemoteException re){
}catch(Exception e){
return result;
4. webservice服务端接收到数据后,取出数据中的 AppID(axcpud123)
telPhone=15261873121, userId=000001, idCert=32132219871234232, sign值
根据AppID到平台数据库中查找AppKeySecret(124jfj3ff3AjifLLefl), 然后对AppId, telPhone, userId, idCert,
AppKeySecret进行MD5加密 得到signNew, 然后比较sign与signNew是否相同,如果相同,则认为客户端与服务端的通讯数据未被修改
小知道点:
1. FastJson对json数据的key值按照a-z排序
public static String getSortStr(JSONObject json,String regx){
StringBuilder sortStr=new StringBuilder();
Iterator<String> iteratorKeys = json.keys();
SortedMap map = new TreeMap();
while (iteratorKeys.hasNext()) {
String key = iteratorKeys.next().toString();
String vlaue = json.optString(key);
map.put(key, vlaue);
Set set = map.entrySet();
Iterator i = set.iterator();
while(i.hasNext()){
Map.Entry me = (Map.Entry)i.next();
String value=me.getValue().toString();
if(!value.isEmpty()){
sortStr.append(regx).append(value);
return sortStr.substring(1,sortStr.length());
2. MD5加密
.生成字符串MD5
.生成字节MD5
.生成文件的MD5值
/**
* <p>Title: MD5Util.java</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2018</p>
* <p>Company: jsjn</p>
* @author zhengwei
* @date 2018年4月28日
* @version 1.0
*/
package com.jsjn.slarms.extSysDock.common.util;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* <p>Title: MD5Util</p>
* <p>Description: MD5算法</p>
* @author zhengwei
* @date 2018年4月28日
*/
public class Md5Util {
private static final String MD5="MD5";
private static final String UTF8="UTF-8";
private static final Integer LENGTH=1024;
/**
* <p>Title: getMd5</p>
* <p>Description: 获取MD5运算之后的值</p>
* @param str
* @return
*/
public final static String getMd5(String str) {
MessageDigest mdInst = null;
byte[] md=null;
try {
mdInst = MessageDigest.getInstance(MD5);
/**
* 使用指定的字节更新摘要
*/
mdInst.update(str.getBytes(UTF8));
/**
* 获得密文
*/
md = mdInst.digest();
} catch (Exception e) {
e.printStackTrace();
return byteArrToHexStr(md);
private static String byteArrToHexStr(byte[] arrB) {
int iLen = arrB.length;
/**
* 每个byte(8位)用两个(16进制)字符才能表示,所以字符串的长度是数组长度的两倍
*/
StringBuffer sb = new StringBuffer(iLen * 2);
for (int i = 0; i < iLen; i++) {
int intTmp = arrB[i];
/**
* 把负数转换为正数
*/
while (intTmp < 0) {
intTmp = intTmp + 256;
/**
* 小于0F的数需要在前面补0
*/
if (intTmp < 16) {
sb.append("0");
sb.append(Integer.toString(intTmp, 16));
return sb.toString();
/**
* <p>Title: getFileInputStreamMD5</p>
* <p>Description: 计算文件流MD5值</p>
* @param in
* @return
* @throws NoSuchAlgorithmException
* @throws IOException
*/
public static String getFileInputStreamMD5(InputStream in) throws NoSuchAlgorithmException, IOException {
MessageDigest digest = null;
byte buffer[] = new byte[1024];
int len;
digest = MessageDigest.getInstance(MD5);
while ((len = in.read(buffer, 0, LENGTH)) != -1) {
digest.update(buffer, 0, len);
in.close();
BigInteger bigInt = new BigInteger(1, digest.digest());
return bigInt.toString(16);