本文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@Overridepublic 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();IteratoriteratorKeys = 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值/*** Title: MD5Util.java
*Description:
*Copyright: Copyright (c) 2018
*Company: jsjn
* @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;/***Title: MD5Util
*Description: MD5算法
* @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;/***Title: getMd5
*Description: 获取MD5运算之后的值
* @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();/***Title: getFileInputStreamMD5
*Description: 计算文件流MD5值
* @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);