程序員的福音 - Apache Commons Codec

此文是系列文章第四篇,前幾篇請(qǐng)點(diǎn)擊鏈接查看

程序猿的福音 - Apache Commons簡(jiǎn)介

程序員的福音 - Apache Commons Lang

程序員的福音 - Apache Commons IO

Apache Commons Codec提供了許多編解碼相關(guān)的工具類。Codec目前最新版本是1.15,最低要求Java7以上。

maven坐標(biāo)如下:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

以下為整體結(jié)構(gòu):

圖片

下面只列舉其中常用的加以說(shuō)明,其余感興趣的可以自行翻閱源碼研究。

01. 二進(jìn)制相關(guān)

二進(jìn)制包主要提供16進(jìn)制、Base64、Base32等的編解碼工具類。

1. 16進(jìn)制(Hex類)

十六進(jìn)制常用于將二進(jìn)制以更簡(jiǎn)短的方式展示,比如MD5是128位,展現(xiàn)起來(lái)太長(zhǎng),而轉(zhuǎn)換為16進(jìn)制后只需要32個(gè)字符即可表示出來(lái)。示例代碼如下

// byte數(shù)組轉(zhuǎn)為16進(jìn)制字符串
String hex = Hex.encodeHexString("123".getBytes());
System.out.println(hex);
// 16進(jìn)制字符串解碼
byte[] src = Hex.decodeHex(hex);
System.out.println(new String(src));

2. Base64,Base32,Base16

Base64是網(wǎng)絡(luò)上最常見(jiàn)的用于傳輸二進(jìn)制數(shù)據(jù)的編碼方式之一,Base64就是一種基于64個(gè)可打印字符來(lái)表示二進(jìn)制數(shù)據(jù)的方法。Base32就是使用32個(gè)可打印字符,Base16就是使用16個(gè)(實(shí)際上相當(dāng)于16進(jìn)制)。

名稱 編碼表字符串 位數(shù)不足是否會(huì)補(bǔ)全
base16 數(shù)字0~9和字母A~F 不會(huì),位數(shù)剛好是 4 的倍數(shù)
base32 大寫(xiě)字母A~Z和數(shù)字2~7 會(huì)
base64 Base大寫(xiě)字母A-Z,小寫(xiě)字母a-z,數(shù)字0~9以及"+","/" 會(huì)
// base64編碼
String base64 = Base64.encodeBase64String("測(cè)試".getBytes());
System.out.println(base64);
// base64解碼
byte[] src = Base64.decodeBase64(base64);
System.out.println(new String(src));
// 字符串是否是base64
Base64.isBase64(base64);

// Base32 Base16 同理

Codec還提供了Base系列的流處理,以流的方式去處理Base編解碼,示例如下

// 以流方式提供Base64編碼和解碼
// 附:"123"的base64編碼為"MTIz"

// 對(duì)輸入流做base64編碼
InputStream is = new ByteArrayInputStream("123".getBytes());
Base64InputStream ebis = new Base64InputStream(is, true);
String enc = IOUtils.toString(ebis, "UTF-8"); // MTIz

// 對(duì)base64數(shù)據(jù)流做解碼
is = new ByteArrayInputStream(enc.getBytes());
Base64InputStream dbis = new Base64InputStream(is, false);
String dec = IOUtils.toString(dbis, "UTF-8"); // 123

// -----------------------

// 將數(shù)據(jù)做base64編碼寫(xiě)入輸出流
final String data = "123";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Base64OutputStream ebos = new Base64OutputStream(baos, true);
IOUtils.write(data, ebos, "UTF-8");
String enc2 = baos.toString(); // MTIz

// 將base64數(shù)據(jù)做解碼寫(xiě)入輸出流
baos = new ByteArrayOutputStream();
Base64OutputStream dbos = new Base64OutputStream(baos, false);
IOUtils.write(data, dbos, "UTF-8");
String dec2 = dbos.toString(); // 123

02. URL相關(guān)

URL之所以要進(jìn)行編碼,是因?yàn)閁RL中有些字符會(huì)引起歧義。

例如URL參數(shù)字符串中使用key=value鍵值對(duì)這樣的形式來(lái)傳參,鍵值對(duì)之間以&符號(hào)分隔,如/s?q=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么勢(shì)必會(huì)造成接收URL的服務(wù)器解析錯(cuò)誤,因此必須將引起歧義的&和=符號(hào)進(jìn)行轉(zhuǎn)義,也就是對(duì)其進(jìn)行編碼。

又如URL的編碼格式采用的是ASCII碼,而不是Unicode,這也就是說(shuō)你不能在URL中包含任何非ASCII字符,例如中文。否則如果客戶端瀏覽器和服務(wù)端瀏覽器支持的字符集不同的情況下,中文可能會(huì)造成問(wèn)題。

URL編碼的原則就是使用安全的字符(沒(méi)有特殊用途或者特殊意義的可打印字符)去表示那些不安全的字符。

編解碼示例代碼如下

URLCodec urlCodec = new URLCodec();
// url編碼
String encUrl = urlCodec.encode("http://x.com?f=哈");
System.out.println(encUrl);
// url解碼
String decUrl = urlCodec.decode(encUrl);
System.out.println(decUrl);

03. 摘要算法

摘要算法是一種單向的散列算法,它滿足以下幾個(gè)特點(diǎn)。

  • 輸入長(zhǎng)度是任意的

  • 輸出長(zhǎng)度是固定的

  • 對(duì)每一個(gè)給定的輸入,計(jì)算輸出是很容易的

  • 不可逆,無(wú)法通過(guò)輸出推算出原數(shù)據(jù)

  • 輸出不依賴于輸入。就是輸入數(shù)據(jù)變動(dòng)一個(gè)字節(jié)結(jié)果會(huì)相差很多

由于摘要算法以上特點(diǎn),主要用于數(shù)據(jù)完整性校驗(yàn)。例如網(wǎng)上的資源一般會(huì)提供一個(gè)摘要值(一般用MD5算法),用戶下載后可以通過(guò)工具對(duì)資源做MD5后和網(wǎng)上給定的值比較,如果不一致說(shuō)明文件不完整了,可能是下載過(guò)程網(wǎng)絡(luò)波動(dòng)內(nèi)容有丟失,也可能被人篡改過(guò)。

也可以做數(shù)據(jù)的指紋,比如網(wǎng)盤(pán)秒傳,就是利用摘要值做判斷??蛻舳松蟼髑跋葘?duì)文件做摘要值,傳給服務(wù)端,服務(wù)端發(fā)現(xiàn)有相同摘要的文件說(shuō)明兩個(gè)文件內(nèi)容是一致的,這樣就無(wú)需上傳直接將文件存儲(chǔ)路徑指向這個(gè)文件就可以了,既實(shí)現(xiàn)了秒傳,還節(jié)約了服務(wù)器磁盤(pán)空間(不同用戶相同內(nèi)容的文件實(shí)際上指向的是同一份文件)。

很多系統(tǒng)也將密碼做md5后存儲(chǔ),其中這種方式并不安全。md5已經(jīng)很很多公開(kāi)結(jié)果了,并且使用彩虹表碰撞也很容易破解了。所以并不建議使用md5存儲(chǔ)密碼。密碼推薦使用BCrypt算法。

摘要算法主要有以下幾個(gè)

  • MD(Message Digest):消息摘要

  • SHA(Secure Hash Algorithm):安全散列

  • MAC(Message Authentication Code):消息認(rèn)證碼

1. MD系列

主要有MD2、MD4、MD5,目前一般常用MD5

// 如果使用Java自帶的api需要十多行才能實(shí)現(xiàn)md5算法

// 對(duì)數(shù)據(jù)做md5,參數(shù)支持字符串,字節(jié)數(shù)據(jù),輸入流
String md5 = DigestUtils.md5Hex("測(cè)試");

2. SHA系列

SHA系列有SHA-1、SHA-224、SHA-256、SHA-384、SHA-512,SHA3-224、SHA3-256、SHA3-384、SHA3-512等。目前安全起見(jiàn)一般選擇256以上,推薦384以上。當(dāng)然摘要越長(zhǎng)則計(jì)算耗時(shí)也越長(zhǎng),需要根據(jù)需求權(quán)衡。

// 參數(shù)支持字符串,字節(jié)數(shù)據(jù),輸入流
String sha1 = DigestUtils.sha1Hex("測(cè)試");
String sha256 = DigestUtils.sha256Hex("測(cè)試");
String sha384 = DigestUtils.sha384Hex("測(cè)試");
String sha512 = DigestUtils.sha512Hex("測(cè)試");
String sha3_256 = DigestUtils.sha3_256Hex("測(cè)試");
String sha3_384 = DigestUtils.sha3_384Hex("測(cè)試");
String sha3_512 = DigestUtils.sha3_512Hex("測(cè)試");

3. HMAC系列

HMAC(keyed-Hash Message Authentication Code)系列是包含密鑰的散列算法,包含了MD和SHA兩個(gè)系列的消息摘要算法。融合了MD,SHA:

MD系列:HMacMD2,HMacMD4,HMacMD5

SHA系列:HMacSHA1,HMacSHA224,HMacSHA256,HMacSHA38

,HMacSHA512

String key = "asdf3234asdf3234asdf3234asdf3234";
String valueToDigest = "測(cè)試數(shù)據(jù)"; // valueToDigest參數(shù)支持字節(jié)數(shù)據(jù),流,文件等
// 做HMAC-MD5摘要
String hmacMd5 = new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
// 做HMAC-sha摘要
String hmacSha256 = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
String hmacSha384 = new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
String hmacSha512 = new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);

04. 命令行

codec包還提供了一個(gè)命令行做摘要算法的入口。

java -cp ./commons-codec-1.15.jar org.apache.commons.codec.cli.Digest MD5 123

05. 總結(jié)

除了以上介紹的工具類外,還有其他不是很常用的就不多做介紹了。感興趣的可以自行翻閱源碼研究。

后續(xù)章節(jié)我將繼續(xù)給大家介紹commons中其他好用的工具類庫(kù),期待你的關(guān)注。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容