一、https+xml服务端编写
- keytool -genkey -alias server_jks_cennavi -keyalg RSA -keypass 123456 -storepass 123456 -keystore server.jks -validity 3650
1.1.2 导出服务端证书
- keytool -export -trustcacerts -alias server_jks_cennavi -file server.cer -keystore server.jks -storepass 123456
1.1.3 创建客户端KeyStore
- keytool -genkey -alias client_p12_cennavi -keyalg RSA -keypass 123456 -storepass 123456 -keystore client.p12 -validity 3650 -storetype PKCS12
1.1.4 导出客户端Cer证书
- keytool -export -trustcacerts -alias client_p12_cennavi -file client.cer -keystore client.p12 -storepass 123456 -storetype PKCS12
1.1.5 交换证书
交换导入服务端和客户端证书,作为双方信任证书。
- keytool -import -trustcacerts -alias client_p12_cennavi -file client.cer -keystore server.jks
- keytool -import -trustcacerts -alias server_jks_cennavi -file server.cer -keystore client.jks
1.2 tomcat https配置
- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true"
- clientAuth="true" sslProtocol="TLS" keystoreFile="C:\Users\hsinghsu\server.jks" keystorePass="123456"
- truststoreFile="C:\Users\hsinghsu\server.jks" truststorePass="123456"/>
注:以上配置为https双向验证,若只要https服务端的单向验证,则将clientAuth="true" 和truststoreFile="C:\Users\hsinghsu\server.jks" truststorePass="123456" 配置去掉即可。
1.3 服务端java代码编写
1.3.1 编写servlet服务端代码
编写servlet代码,用于获取用户https+xml/http+xml请求,解析请求后进行相应业务为逻辑处理返回相应信息给请求方。- package com.hsinghsu.test.web.servlet;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.zip.GZIPOutputStream;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.dom4j.Attribute;
- import org.dom4j.Document;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- public class TestInterfaceServlet extends HttpServlet
- {
- /**
- * 对外接口主入口
- * 用于获取用户请求,返回用户请求使用。
- */
- public void service(ServletRequest request, ServletResponse response)
- throws ServletException, IOException
- {
- HttpServletResponse httpResponse = (HttpServletResponse)response;
- HttpServletRequest httprequest = (HttpServletRequest)request;
- httpResponse.setContentType("text/html;charset=UTF-8");
- Map<String, String> mapHeader = getHeaderMap(httprequest);// 获取http头信息
- String requestXml = "";//请求过来的xml报文
- String responseXml = "";//返回的xml报文
- Document doc = null;
- InputStream is = request.getInputStream();
- System.out.println("======http header timestamp is :" + mapHeader.get("timestamp"));
- SAXReader saxReader = new SAXReader();
- Map<String, String> map = new HashMap<String, String>();
- try
- {
- doc = saxReader.read(is);
- requestXml = doc.asXML();
- System.out.println("======request xml :" + requestXml);
- Element rootElm = doc.getRootElement();//从root根节点获取请求报文
- map = parseXML(rootElm, new HashMap<String, String>());
- String msgname = map.get("msgname");//从http body中获取到的msgname值
- // 是否https访问
- if (request.isSecure())
- {
- //https访问
- if ("loginReq".equals(msgname))
- {
- System.out.println("the https+xml request is loginReq");
- responseXml =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ecity><msgname>loginRep</msgname><msgversion>1.0.0</msgversion><result><rspcode>0</rspcode><rspdesc>成功</rspdesc></result><svccont><uid>111</uid></svccont></ecity>";
- }
- else
- {
- System.out.println("请求接口名称不在本系统内");
- responseXml =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ecity><msgversion>1.0.0</msgversion><result><rspcode>1</rspcode><rspdesc>请求接口名称不在本系统内</rspdesc></result></ecity>";
- }
- }
- else
- {
- //http访问
- if ("logOutReq".equals(msgname))
- {
- System.out.println("the http+xml request is logOut");
- responseXml =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ecity><msgname>logOutRep</msgname><msgversion>1.0.0</msgversion><result><rspcode>0</rspcode><rspdesc>成功</rspdesc></result><svccont><uid>111</uid></svccont></ecity>";
- }
- else
- {
- System.out.println("请求接口名称不在本系统内");
- responseXml =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ecity><msgversion>1.0.0</msgversion><result><rspcode>1</rspcode><rspdesc>请求接口名称不在本系统内</rspdesc></result></ecity>";
- }
- }
- }
- catch (Exception e1)
- {
- System.out.println("请求数据不正确");
- responseXml =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ecity><msgversion>1.0.0</msgversion><result><rspcode>2</rspcode><rspdesc>请求数据不正确</rspdesc></result></ecity>";
- }
- // 对报文进行压缩处理
- String AcceptEncoding = "gzip";
- if (mapHeader != null)
- AcceptEncoding = mapHeader.get("Accept-Encoding");
- if (null != AcceptEncoding && "gzip".equals(AcceptEncoding))
- {
- // 使用gzip压缩报文
- System.out.println("======output response xml with gzip is : " + responseXml);
- response.getOutputStream().write(gZip(responseXml.getBytes()));
- response.getOutputStream().flush();
- response.getOutputStream().close();
- }
- else
- {
- // 不压缩报文,直接传输
- System.out.println("======output response xml without gzip is : " + responseXml);
- response.getOutputStream().write(responseXml.getBytes());
- response.getOutputStream().flush();
- response.getOutputStream().close();
- }
- }
- /**
- * 获取http头信息
- * <功能详细描述>
- * @param request
- * @return
- * @see [类、类#方法、类#成员]
- */
- public Map<String, String> getHeaderMap(HttpServletRequest request)
- {
- Map<String, String> map = new HashMap<String, String>();
- if (null != request.getHeader("msgname") && !"".equals(request.getHeader("msgname")))
- map.put("msgname", request.getHeader("msgname"));
- if (null != request.getHeader("Accept-Encoding") && !"".equals(request.getHeader("Accept-Encoding")))
- map.put("Accept-Encoding", request.getHeader("Accept-Encoding"));
- if (null != request.getHeader("timestamp") && !"".equals("timestamp"))
- map.put("timestamp", request.getHeader("timestamp"));
- return map;
- }
- /**
- * 将xml解析成map键值对
- * <功能详细描述>
- * @param ele 需要解析的xml对象
- * @param map 入参为空,用于内部迭代循环使用
- * @return
- * @see [类、类#方法、类#成员]
- */
- private Map<String, String> parseXML(Element ele, Map<String, String> map)
- {
- for (Iterator<?> i = ele.elementIterator(); i.hasNext();)
- {
- Element node = (Element)i.next();
- System.out.println("======parseXML node name:" + node.getName());
- if (node.attributes() != null && node.attributes().size() > 0)
- {
- for (Iterator<?> j = node.attributeIterator(); j.hasNext();)
- {
- Attribute item = (Attribute)j.next();
- System.out.println("======parseXML property name:" + item.getName() + " property value:"
- + item.getValue() + "\n");
- map.put(item.getName(), item.getValue());
- }
- }
- if (node.getText().length() > 0)
- {
- System.out.println("======parseXML node value:" + node.getText());
- map.put(node.getName(), node.getText());
- }
- if (node.elementIterator().hasNext())
- {
- parseXML(node, map);
- }
- }
- return map;
- }
- /**
- * gZip压缩方法
- * 将原报文通过gzip压缩
- * @param data
- * @return
- * @see [类、类#方法、类#成员]
- */
- public static byte[] gZip(byte[] data)
- {
- byte[] b = null;
- try
- {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- GZIPOutputStream gzip = new GZIPOutputStream(bos);
- gzip.write(data);
- gzip.finish();
- gzip.close();
- b = bos.toByteArray();
- bos.close();
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- return b;
- }
- }
1.3.2 web.xml配置
在web.xml中配置访问该接口的servlet,详见配置如下:- <servlet>
- <servlet-name>interfaceServlet</servlet-name>
- <servlet-class>com.hsinghsu.test.web.servlet.TestInterfaceServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>interfaceServlet</servlet-name>
- <url-pattern>/interface</url-pattern>
- </servlet-mapping>
1.3.3 启动服务端
启动服务端tomcat。服务端的访问地址为:https://127.0.0.1:8843/testhttps/interface二、https+xml客户端编写
2.1 编写客户端java代码,示例如下:
- package com.hsinghsu.test.web.servlet;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
- import org.apache.commons.httpclient.HttpClient;
- import org.apache.commons.httpclient.HttpStatus;
- import org.apache.commons.httpclient.methods.PostMethod;
- import org.apache.commons.httpclient.methods.StringRequestEntity;
- import org.apache.commons.httpclient.params.HttpMethodParams;
- import org.dom4j.Document;
- import org.dom4j.io.SAXReader;
- public class TestReqServlet extends HttpServlet
- {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException
- {
- // String sURL = "http://127.0.0.1:8080/testhttps/interface";
- String sURL = "https://127.0.0.1:8443/testhttps/interface";
- String xml =
- "<?xml version='1.0' encoding='UTF-8'?><ecity><msgname>loginReq</msgname><timestamp>20140422094111</timestamp><svccont><token>112255</token></svccont></ecity>";
- toHTTPS(sURL, xml);
- }
- /**
- * https调用
- * <功能详细描述>
- * @param sURL 请求URL
- * @param xml 请求报文
- * @return
- * @throws IOException
- * @see [类、类#方法、类#成员]
- */
- public String toHTTPS(String sURL, String xml)
- throws IOException
- {
- sURL = "https://127.0.0.1:8443/testhttps/interface";
- System.setProperty("javax.net.ssl.trustStore", "C:\\Users\\hsinghsu\\Desktop\\https\\client.jks");
- System.setProperty("javax.net.ssl.trustStorePassword", "123456");
- System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
- System.setProperty("javax.net.ssl.keyStore", "C:\\Users\\hsinghsu\\Desktop\\https\\client.p12");
- System.setProperty("javax.net.ssl.keyStorePassword", "123456");
- //注:去掉以上5行则表示使用http协议访问
- String resultXML = "";
- HttpClient httpClient = null;
- PostMethod postMethod = null;
- try
- {
- httpClient = new HttpClient();
- // 设置超时时间
- httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(30000);
- httpClient.getHttpConnectionManager().getParams().setSoTimeout(30000);
- postMethod = new PostMethod(sURL);
- postMethod.setRequestEntity(new StringRequestEntity(xml, "text/html", "UTF-8"));
- postMethod.setRequestHeader("Content-Type", "text/xml;charset=UTF-8");
- postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
- int statusCode = httpClient.executeMethod(postMethod);
- if (statusCode != HttpStatus.SC_OK)
- {
- System.out.println("Call method failed: " + postMethod.getStatusLine());
- }
- BufferedReader in = null;
- try
- {
- in = new BufferedReader(new InputStreamReader(postMethod.getResponseBodyAsStream(), "utf-8"));
- SAXReader saxReader = new SAXReader();
- Document doc = saxReader.read(new InputStreamReader(postMethod.getResponseBodyAsStream(), "utf-8"));
- resultXML = doc.asXML();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- finally
- {
- if (in != null)
- {
- try
- {
- in.close();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- }
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- finally
- {
- if (postMethod != null)
- {
- postMethod.releaseConnection();
- }
- }
- return resultXML;
- }
- }
三、soapUI测试https+xml接口
打开soapUI,File-->Preferences-->SSL Settings,导入client.p12,输入密码即可
注:以上配置为https双向验证,若只要https服务端的单向验证,则去掉client.p12 SOAPUI配置证书即可。