總想自己動動手系列·1·本地和外網(Liunx伺服器上部署的web專案)按照自定義的報文格式進行互動(一)
阿新 • • 發佈:2018-11-08
一、準備工作
(1)有一臺屬於自己的雲伺服器,併成功部署和釋出一個web專案(當然,本質上來說Java-Project也沒問題),通過外網IP可以正常訪問該web專案。
需要說明的是:任何web專案,只要成功部署後在外網上能訪問到即可。本案例注重修改web對請求的監聽和過濾的處理(下個版本在弄這個啦!)。
(2)本地新建Java-project,需要準備一些jar包,比如:AES加密相關的包,BASE64加相關的包,至於通訊相關的類,JDK的java.io和java.net自帶。
二、Code部分
(1)第一步:首先建立一個介面,先定義好規則(比如:需要用到哪些方法等)
1 package com.xfwl.message.serverMsg; 2 3 import java.net.URL; 4 import java.net.URLConnection; 5 import java.util.Map; 6 7 /** 8 * 通訊類介面 9 * @function 10 * @author 小風微涼 11 * @time 2018-11-8 下午2:03:39 12 */ 13 public interface IHttpClient { 14 /** 15 * 預設編碼格式 16 */17 static final String CHARTER_ENCODE="UTF-8"; 18 //建立報文傳送物件 19 public URLConnection getClient(String url); 20 //建立傳送報文方法 21 public boolean sendDataMsg(URLConnection url,String encygen); 22 //建立接收報文方法 23 public StringBuffer receiveDataMsg(URLConnection url,String encygen); 24 //建立報文加密方法 25 public StringBuffer encryptMsg(String data,String encygen); 26 //建立報文解密方法 27 public StringBuffer deCioherMsg(String data,String encygen); 28 }
(2)第二步:準備要用到的工具類,比如報文的加密、解密等,下面用到的時AES加密(加解密時都需要加密因子,中間使用了Base64改變編碼格式)
1 package com.xfwl.message.serverMsg; 2 3 import java.security.NoSuchAlgorithmException; 4 import java.security.SecureRandom; 5 import java.util.logging.Level; 6 import java.util.logging.Logger; 7 8 import javax.crypto.Cipher; 9 import javax.crypto.KeyGenerator; 10 import javax.crypto.SecretKey; 11 import javax.crypto.spec.SecretKeySpec; 12 import org.apache.commons.codec.binary.Base64; 13 /** 14 * AES加密、解密處理工具(加密因子+base64的加解密) 15 * @function 16 * @author 小風微涼 17 * @time 2018-11-8 下午2:35:15 18 */ 19 public class AESUtil { 20 //預設加密祕鑰 21 private static final String KEY_ALGORITHM = "AES"; 22 //預設的加密演算法 23 private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; 24 /** 25 * AES 加密操作 26 * 27 * @param content 待加密內容 28 * @param password 加密密碼 29 * @return 返回Base64轉碼後的加密資料 30 */ 31 public static String encrypt(String content, String password) { 32 try { 33 Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 建立密碼器 34 35 byte[] byteContent = content.getBytes("utf-8"); 36 37 cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化為加密模式的密碼器 38 39 byte[] result = cipher.doFinal(byteContent);// 加密 40 41 return Base64.encodeBase64String(result);//通過Base64轉碼返回 42 } catch (Exception ex) { 43 Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex); 44 } 45 46 return null; 47 } 48 49 /** 50 * AES 解密操作 51 * 52 * @param content 資料 53 * @param password 加密因子 54 * @return 55 */ 56 public static String decrypt(String content, String password) { 57 try { 58 //例項化 59 Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); 60 61 //使用金鑰初始化,設定為解密模式 62 cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password)); 63 64 //執行操作 65 byte[] result = cipher.doFinal(Base64.decodeBase64(content)); 66 67 return new String(result, "utf-8"); 68 } catch (Exception ex) { 69 Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex); 70 } 71 72 return null; 73 } 74 75 /** 76 * 生成加密祕鑰 77 * @param password 加密因子 78 * @return 79 */ 80 private static SecretKeySpec getSecretKey(final String password) { 81 //返回生成指定演算法金鑰生成器的 KeyGenerator 物件 82 KeyGenerator kg = null; 83 try { 84 kg = KeyGenerator.getInstance(KEY_ALGORITHM); 85 //AES 要求金鑰長度為 128 86 kg.init(128, new SecureRandom(password.getBytes())); 87 //生成一個金鑰 88 SecretKey secretKey = kg.generateKey(); 89 90 return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 轉換為AES專用金鑰 91 } catch (NoSuchAlgorithmException ex) { 92 Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex); 93 } 94 return null; 95 } 96 /** 97 * 測試 98 * @param args 99 */ 100 public static void main(String[] args) { 101 String s = "hello,xfwl"; 102 System.out.println("明文(加密前):" + s); 103 //加密 104 String s1 = AESUtil.encrypt(s, "xfwl"); 105 System.out.println("加密後:" + s1); 106 //解密 107 System.out.println("解密後:"+AESUtil.decrypt(s1, "xfwl")); 108 } 109 }
(3)第三步:開始實現步驟一中定義的規則
1 package com.xfwl.message.serverMsg; 2 3 import java.io.BufferedOutputStream; 4 import java.io.BufferedReader; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.InputStreamReader; 8 import java.io.OutputStream; 9 import java.io.OutputStreamWriter; 10 import java.net.MalformedURLException; 11 import java.net.URL; 12 import java.net.URLConnection; 13 import java.util.HashMap; 14 import java.util.Iterator; 15 import java.util.Map; 16 import java.util.Set; 17 import java.util.Map.Entry; 18 19 public class HTTPServerClient implements IHttpClient { 20 /** 21 * 報文上送資料集合 22 */ 23 private Map<String,Object> sendMap=null; 24 /** 25 * 構造器 26 */ 27 public HTTPServerClient(Map<String,Object> sendMap){ 28 this.sendMap=sendMap; 29 } 30 /** 31 * 獲取連線物件 32 */ 33 public URLConnection getClient(String url) { 34 URL u=null; 35 try { 36 u= new URL(url); 37 } catch (MalformedURLException e) { 38 e.printStackTrace(); 39 } 40 System.out.println("建立["+url+"]連結...."); 41 //獲取連線物件 42 URLConnection uc=null; 43 try { 44 uc = u.openConnection(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 return uc; 49 } 50 /** 51 * 傳送報文 52 */ 53 public boolean sendDataMsg(URLConnection uc,String encygen) { 54 //開啟輸出流 55 uc.setDoOutput(true); 56 //獲取輸出流物件 57 OutputStream raw=null; 58 OutputStream buffered = null; 59 OutputStreamWriter out=null; 60 try { 61 raw = uc.getOutputStream(); 62 buffered = new BufferedOutputStream(raw); 63 out = new OutputStreamWriter(buffered, CHARTER_ENCODE); 64 StringBuffer data=createMsgFormat(sendMap); 65 System.out.println("傳送報文:"+data); 66 out.write(encryptMsg(data.toString(),encygen).toString()); 67 out.flush(); 68 System.out.println("關閉連線"); 69 out.close(); 70 } catch (IOException e) { 71 e.printStackTrace(); 72 return false; 73 } 74 return true; 75 } 76 /** 77 * 接收報文 78 */ 79 public StringBuffer receiveDataMsg(URLConnection uc,String deciogen) { 80 //獲取到返回資料的輸入流 81 InputStream is=null; 82 BufferedReader br=null; 83 StringBuffer blzRspXml = new StringBuffer(); 84 try { 85 is = uc.getInputStream(); 86 br = new BufferedReader(new InputStreamReader(is,CHARTER_ENCODE)); 87 String line = ""; 88 System.out.println("獲取返回資料:"); 89 while((line = br.readLine()) != null){ 90 //讀取返回資料,分行讀取 91 //System.out.println(deCioherMsg(line.trim(),deciogen));//解密 92 System.out.println(line.trim()); 93 blzRspXml.append(line.trim()); 94 } 95 } catch (IOException e) { 96 e.printStackTrace(); 97 } 98 return blzRspXml; 99 } 100 /** 101 * 加密資料 102 */ 103 public StringBuffer encryptMsg(String data,String encygen) { 104 return new StringBuffer(AESUtil.encrypt(data, encygen)); 105 } 106 /** 107 * 解析資料 108 */ 109 public StringBuffer deCioherMsg(String data,String deciogen) { 110 return new StringBuffer(AESUtil.decrypt(data, deciogen)); 111 } 112 113 /** 114 * 生成送報文: 115 * 上送報文和響應報文都需要約定一種報文格式 116 */ 117 private StringBuffer createMsgFormat(Map<String,Object> dataMap){ 118 StringBuffer msg=new StringBuffer(); 119 msg.append("<service>"); 120 msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); 121 msg.append("<SYS_HEAD>"); 122 //存放:業務型別碼 123 msg.append("<HEAD_BSNCODE>100001</HEAD_BSNCODE>"); 124 msg.append("</SYS_HEAD>"); 125 msg.append("<BODY>"); 126 //存放:業務資料 127 Set<Entry<String, Object>> set = dataMap.entrySet(); 128 Iterator<Entry<String, Object>> it = set.iterator(); 129 while (it.hasNext()) { 130 Entry<String, Object> ey = it.next(); 131 String key = ey.getKey(); 132 String value = (String) ey.getValue(); 133 msg.append("<"+key+">"+value+"</"+key+">"); 134 } 135 msg.append("</BODY>"); 136 msg.append("</service>"); 137 return msg; 138 } 139 /** 140 * 解析響應報文: 141 * @param args 142 */ 143 private StringBuffer parseRecMsgFormat(String data){ 144 //...待續... 145 146 147 148 return null; 149 } 150 public static void main(String[] args) { 151 Map<String,Object> sendMap =new HashMap<String, Object>(); 152 sendMap.put("ADMIN", "小風微靈"); 153 sendMap.put("PWD", "xfwl123"); 154 //System.out.println(createMsgFormat(sendMap)); 155 } 156 }
(4)第四步:開始測試一下
1 package com.xfwl.message.test; 2 3 import java.net.URLConnection; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 import com.xfwl.message.serverMsg.HTTPServerClient; 8 9 public class TestAction3 { 10 public static void main(String[] args) { 11 Map<String,Object> sendMap =new HashMap<String, Object>(); 12 sendMap.put("ADMIN", "小風微靈"); 13 sendMap.put("PWD", "xfwl123"); 14 15 HTTPServerClient client=new HTTPServerClient(sendMap); 16 URLConnection uc=client.getClient("http://47.105.58.153:3000"); 17 client.sendDataMsg(uc,"lvjun"); 18 client.receiveDataMsg(uc,"lvjun"); 19 } 20 }
看一下測試結果:
1 建立[http://47.105.58.153:3000]連結.... 2 傳送報文[明文]:<service><?xml version="1.0" encoding="UTF-8"?><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><ADMIN>小風微靈</ADMIN><PWD>xfwl123</PWD></BODY></service> 3 傳送報文[密文]:UCr7pP6rDXPVlZzhcTRD20JHzoQSI7/Tb82YL6m6O25tD37RE6lW062yoRvdAv4eWxKWT2shrt97 4 t2ZN+kjNVqkhLRaEw96yr1arAWtxri0pX0W3LYXw0Gw4LoTWsPb09a0JRv5p35Dt0QICN/Ve0+mP 5 ayN+jCSFE3DKk5xusgSzua3adfnEdELhxbR33+CL09yI+Rc8In2NjYrsg24kkM29dJaWSRGm+ahn 6 26OUQnI= 7 8 關閉連線 9 獲取返回資料: 10 {"status":"1","msg":"未登入!","result":""}
三、接下來準備要做的事情
從上面的測試結果來看,已經成功完成了第一步,即將本地的請求(用自定義的報文格式處理請求資料)傳送到雲伺服器上部署的web工程服務上,接下來要做的就是在web工程上動手,監聽這類請求,根據約定的加密因子和
報文規則,解密和解析析xml報文,獲取其中的請求資料,經行業務邏輯處理後按照約定的加密方式和報文規則,生成對應的響應報文,返回給本地的Java-Project,本地Java-Project再解密解析響應報文,獲取響應資料,從而經行本
地的業務邏輯處理。
一步步來吧,只要腳步不停下,就是在進步......