base64問題引入
在此之前,問一個問題,什麼是BASE64加解密呢??
計算機中的任何數據都是按照ascii碼存儲的,但是ascii碼的128~255之間的值是不可見字符。而在網絡上交換數據的時候,比如從A地傳到B地,往往要經過多個路由設備。由於不同的設備對字符的處理方式有一些不同,這樣那些不可見字符就有可能被處理錯誤,這樣就不利於傳輸。所以就先把數據先做一個Base64編碼,統統變成可見字符,這樣出錯的可能性就大降低了。
對於證書來說,特別是根證書,一般都是做Base64編碼的,因爲它要在網上被許多人下載,電子郵件的附件一般也作Base64編碼的,因爲一個附件數據往往是有不可見字符的。
那麼Base64到底是怎麼樣編碼的呢?
簡單來說:任何一個數據無非可以看作一個比特流,如01000100010011101100111010111100011001010…,那麼我們取6個比特作爲一組。計算它的ascii值,得到一個字符,這個字符肯定是可見字符,好,把它對應的字符寫出來。再取6個比特,計算,,,如此下去,直到最後,就完成可編碼。
Base64的加密規則
- 標準Base64只有64個字符(英文大小寫,數字,和+,/)以及用作後綴等號;
- base64是把3個字節變成4個可打印的字符,所以base64編碼後的字符一定能被4整除(不算用作後綴的等號。
- 等號一定用作後綴),且數目一定是0個,1個或2個。這是因爲如果原文長度不能被3整除,base64要在後面添加\0,湊齊3n。爲了正確還原,添加了幾個\n就加上了幾個等號。顯然添加等號的數目只能是0,1,2
- 嚴格來說,base64不能算是一種加密,只能說是編碼轉換。使用base64的初衷,是爲了方便把含有不可見字符串的信息用可見字符串表示出來,以便複製粘貼。
一個Base64的應用場景
提供一個工作中用到過的base64場景
一個xml當中包含另一個xml數據,此時如果將xml數據直接寫入顯然不合適,將xml進行適當編碼存入較爲方便,事實上xml當中的字符一般都是可見字符(0-127之間),但是由於中文的存在,可能存在不可見字符,直接將字符打印在外層xml的數據中顯然不合理,那麼怎麼辦呢?
可以使用base64進行編碼,然後存入xml,解碼反之
其實還有個辦法,將byte的值寫在xml當中,空格或者,分開,這樣也可以將byte數據傳入,不過這樣更浪費空間,並且不易保存.
另一個,比如http協議當中的key value字段,必須進行URLEncode 不然出現的等號可能使解析失敗 空格也會使http請求解析出現問題,比如 請求行就是以空格來劃分的 POST /guowuxin/hehe HTTP/1.1
又比如有些文本協議不支持不可見字符的傳遞,只能用大於32的可見字符來傳遞信息(協議規定)
在工作中遇到的字節數組在系統之間傳遞的問題。
package com.zhangqi.servlet;
public class DownLoadTest {
RequestMapping(value ="/sdbDownLoadAttachment", method =RequestMethod.POST)
public Object sdbDownLoadAttachment(@RequestBody String paramStr, HttpServletResponse response, HttpServletRequest request) throws IOException {
LogUtil.info("sdbDeleteAttachment:" + paramStr);
Map<String, Object> paramMap = (Map<String, Object>) JSONObject.parse(paramStr);
String key = (String) paramMap.get("key");
Response iobsResponse = sdbaoUploadIobsServiceImpl.downLoadAttachment(key);
if (iobsResponse.isOK()) {
try (InputStream ins = iobsResponse.downloadFileStream()) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int length = 1;
while ((length = ins.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, length);
}
byte[] bytes2 = byteArrayOutputStream.toByteArray();
BASE64Encoder base64Encoder = new BASE64Encoder();
String encode = base64Encoder.encode(bytes2);
HashMap<String, Object> resultMap1 = Maps.newHashMap();
resultMap1.put("byte", bytes2);
return resultMap1;
} catch (IOException e) {
LogUtil.error(e, "文件流異常");
}
} else {
return new ResponseResult.ResponseBuilder().builderResponseCode(EnumForSaleBaseResult.CODE_800000.getResultCode()).builderResponseMsg("失敗" + "錯誤碼爲:" + iobsResponse.code() + "錯誤信息爲:"
+ iobsResponse.error()).build();
}
return null;
}
}
@RestController
public class DownLoadTest {
@RequestMapping("/testDownload")
public void testDownload(@RequestBody String param) throws Exception {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json;charset=utf-8");
headers.set("Accept", "application/json;charset=UTF-8");
HttpEntity entity = new HttpEntity(param, headers);
ResponseEntity<Map> exchange = restTemplate.exchange("http://localhost:44631/accidentGroup/sdbDownLoadAttachment", HttpMethod.POST, entity, Map.class);
Map body = exchange.getBody();
String aByte2 = (String) body.get("byte");
System.out.println(aByte2.getClass());
BASE64Decoder base64Decoder = new BASE64Decoder();
base64Decoder.decodeBuffer(aByte2) byte[] bytes3 = aByte2.getBytes();
byte[] aByte = (byte[]) body.get("byte");
FileOutputStream fileOutputStream = new FileOutputStream(new File("D://a.xls"));
fileOutputStream.write(aByte, 0, aByte.length);
fileOutputStream.flush();
fileOutputStream.close();
}
}
在這裏記錄一下