將文字在網(wǎng)絡(luò)中進(jìn)行傳輸?shù)臅r(shí)候,如果存在非ASCII碼字符,很容易出現(xiàn)亂碼問題,要解決也不難,在傳輸?shù)奈淖稚嫌肬RLEncoder進(jìn)行編碼,將它變成全部是ASCII碼的形式,這樣在網(wǎng)絡(luò)傳輸中就不會(huì)受到影響;在另一側(cè),將收到的文字用URLDecoder加碼就能還原文字原本的摸樣。
IMSample中涉及到文字的混合加密,情況稍復(fù)雜一點(diǎn),但流程還是一樣的。
相關(guān)涉及編碼和解碼的工具類:
package com.heyang.common.code;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* UTF8轉(zhuǎn)碼器
* @author heyang
*
*/
public class UTF8Coder{
private static final String UTF_8 = "utf-8";// 編碼形式
/**
* 對(duì)文字進(jìn)行UTF8轉(zhuǎn)碼
* @param str
* @return
*/
public static String encode(String str){
try {
return URLEncoder.encode(str, UTF_8);
} catch (UnsupportedEncodingException e) {
return null;
}
}
/**
* 將轉(zhuǎn)碼后的文字還原
* @param str
* @return
*/
public static String decode(String str){
try {
return URLDecoder.decode(str, UTF_8);
} catch (UnsupportedEncodingException e) {
return null;
}
}
}
變化后的加密器代碼:
package com.heyang.common.cipher;
import org.apache.commons.codec.binary.Base64;
import com.heyang.common.code.AESSecurityCoder;
import com.heyang.common.code.Base64SecurityUtil;
import com.heyang.common.code.RSASecurityCoder;
import com.heyang.common.code.UTF8Coder;
/**
* 對(duì)消息進(jìn)行加密的加密器
* 說明:
* 作者:何楊(heyang78@gmail.com)
* 創(chuàng)建時(shí)間:2010-12-27 下午07:00:29
* 修改時(shí)間:2010-12-27 下午07:00:29
*/
public class IMMsgEncrypter{
// 經(jīng)加密的消息
private String cipheredMsg;
/**
* 構(gòu)造函數(shù)
* @param plainMsg 未加密的消息
* @param otherSideRSAPublicKey 對(duì)方RSA公鑰
* @param rsaCoder 己方RSA編碼器
* @param aesCoder 己方AES編碼器
* @throws IMMsgEncryptException
*/
public IMMsgEncrypter(String plainMsg,String otherSideRSAPublicKey,RSASecurityCoder rsaCoder,AESSecurityCoder aesCoder) throws IMMsgEncryptException{
try{
// 防止亂碼
plainMsg=UTF8Coder.encode(plainMsg);
// 對(duì)明文進(jìn)行AES加密
byte[] aesArr=aesCoder.getEncryptByteArray(plainMsg); // 對(duì)明文進(jìn)行AES加密
String cipherText=Base64.encodeBase64String(aesArr);// 得到AES加密后的密文
// 使用RSA對(duì)AES密鑰進(jìn)行加密
String key=aesCoder.getAesKey();// 取得AES的密鑰
String aesKey="";
try{
byte[] clientRsaKeyArr=null;
clientRsaKeyArr=Base64.decodeBase64(otherSideRSAPublicKey);
byte[] rsaArr=rsaCoder.getEncryptArray(key, clientRsaKeyArr);
aesKey=Base64.encodeBase64String(rsaArr);
}
catch(Exception ex){
throw new IMMsgEncryptException("使用對(duì)方RSA公鑰加密己方AES鑰匙時(shí)發(fā)生異常.");
}
// 在發(fā)出的密文前附帶經(jīng)服務(wù)器RSA公鑰加密的AES密鑰
StringBuilder sb=new StringBuilder();
sb.append("<aeskey>"+aesKey+"</aeskey>");
sb.append("<rsakey>"+rsaCoder.getPublicKeyString()+"</rsakey>");
sb.append("<text>"+cipherText+"</text>");
// 最后對(duì)整體進(jìn)行Base64加密
cipheredMsg=Base64SecurityUtil.getEncryptString(sb.toString());
}
catch(Exception ex){
throw new IMMsgEncryptException("加密消息時(shí)發(fā)生異常,異常信息為"+ex.getMessage()+".");
}
}
public String getCipheredMsg() {
return cipheredMsg;
}
}
修改后的解碼器代碼:
package com.heyang.common.cipher;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.codec.binary.Base64;
import com.heyang.common.code.AESSecurityCoder;
import com.heyang.common.code.Base64SecurityUtil;
import com.heyang.common.code.RSASecurityCoder;
import com.heyang.common.code.UTF8Coder;
/**
* 消息解密器
* 說明:
* 作者:何楊(heyang78@gmail.com)
* 創(chuàng)建時(shí)間:2010-12-27 下午07:41:44
* 修改時(shí)間:2010-12-27 下午07:41:44
*/
public class IMMsgDecrypter{
// 固定的三個(gè)節(jié)點(diǎn)名
private static final String TEXT = "text";
private static final String RSAKEY = "rsakey";
private static final String AESKEY = "aeskey";
// 對(duì)方的RSA公鑰
private String otherSideRSAPublicKey;
// 解密后的明文
private String plainMsg;
/**
* 構(gòu)造函數(shù)
* @param cipherMsg 要解密的消息
* @param rsaCoder 己方RSA編碼器
* @param aesCoder 己方AES編碼器
* @throws IMMsgDecryptException
*/
public IMMsgDecrypter(String cipherMsg,RSASecurityCoder rsaCoder,AESSecurityCoder aesCoder) throws IMMsgDecryptException{
try{
// 先用Base64解密密文
cipherMsg=Base64SecurityUtil.getDecryptString(cipherMsg);
// 用正則表達(dá)式得到密鑰文,客戶端的RSA公鑰和密文
String regex="<(\\w+)>((.|\\s)+)</\\1>";
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(cipherMsg);
String cipheredAesKey="";// 經(jīng)服務(wù)器RSA公鑰加密的客戶端AES鑰匙密文
String cipherText="";// 經(jīng)客戶端AES加密的密文
Map<String,String> map=new HashMap<String,String>();
while(matcher.find()){
map.put(matcher.group(1), matcher.group(2));
}
if(map.size()==3){
cipheredAesKey=map.get(AESKEY);
otherSideRSAPublicKey=map.get(RSAKEY);
cipherText=map.get(TEXT);
}
else{
throw new IMMsgDecryptException("解密消息時(shí)發(fā)生異常,原因是消息格式不正確.消息為:"+cipherMsg);
}
// 得到經(jīng)過服務(wù)器RSA私鑰解密后的AES密鑰
String plainAesKey="";
try {
byte[] cipheredAesKeyArr=Base64.decodeBase64(cipheredAesKey);
plainAesKey=rsaCoder.getDecryptString(cipheredAesKeyArr);
} catch (Exception e) {
throw new IMMsgDecryptException("無法解密對(duì)方AES密鑰,異常信息為"+e.getMessage()+",客戶端請(qǐng)求為:"+cipherMsg);
}
// 使用AES密鑰解密出明文
byte[] cipherTextArr=Base64.decodeBase64(cipherText);
plainMsg=aesCoder.getDecryptString(cipherTextArr, plainAesKey);
// UTF08還原
plainMsg=UTF8Coder.decode(plainMsg);
}
catch(Exception ex){
throw new IMMsgDecryptException("解密消息發(fā)生異常,異常信息為"+ex.getMessage()+".");
}
}
public String getOtherSideRSAPublicKey() {
return otherSideRSAPublicKey;
}
public String getPlainMsg() {
return plainMsg;
}
}
以上只是涉及亂碼問題的一個(gè)處理方法,各位還要具體情況具體分析。