今天遇到一個Base64解碼的問題,因此在這里記錄一下。
一. 問題
問題是這樣,服務(wù)器下發(fā)的Base64編碼后的數(shù)據(jù),iOS端調(diào)用系統(tǒng)解碼,解出來為空,但是安卓或者web端解析出來沒問題。
NSString *token = @"eyJzdWIiOiJhYmM0IiwidWlkIjoyMTY0NzQ0LCJzY3AiOlsiUk9MRV9SRUdVTEFSIl0sIm5iZiI6MTYwMzY5Mjg5MywiaXNzIjoiaHR0cDpcL1wvMTkyLjE2OC4yLjk6ODA4NyIsImV4cCI6MTYwMzczNjA5MywiaWF0IjoxNjAzNjkyODkzLCJqdGkiOiJmNDcxOTAyMC0zMGRmLTQ1NDItYjEyMy04YWY0YTVlNDFmNDIifQ";
二. 問題原因
問題的原因在于后端下發(fā)的Base64編碼后的字符串,并沒有嚴(yán)格按照Base64編碼的轉(zhuǎn)化規(guī)則。
Base64編碼原理:
1)將所有字符轉(zhuǎn)化為ASCII碼;
2)將ASCII碼轉(zhuǎn)化為8位二進制;
3)將3個8位二進制歸成一組(不足3個在后邊補0)共24位,再拆分成4組,每組6位;
4)統(tǒng)一在6位二進制前補兩個0湊足8位;
5)將補0后的二進制轉(zhuǎn)為十進制;
6)從Base64編碼表獲取十進制對應(yīng)的Base64編碼;
處理過程說明:
a.轉(zhuǎn)換的時候,將三個byte的數(shù)據(jù),先后放入一個24bit的緩沖區(qū)中,先來的byte占高位。
b.數(shù)據(jù)不足3byte的話,于緩沖區(qū)中剩下的bit用0補足。然后,每次取出6個bit,按照其值選擇查表選擇對應(yīng)的字符作為編碼后的輸出。
c.不斷進行,直到全部輸入數(shù)據(jù)轉(zhuǎn)換完成。
d.如果最后剩下兩個輸入數(shù)據(jù),在編碼結(jié)果后加1個“=”;
e.如果最后剩下一個輸入數(shù)據(jù),編碼結(jié)果后加2個“=”;
f.如果沒有剩下任何數(shù)據(jù),就什么都不要加,這樣才可以保證資料還原的正確性。
也就是說后端下發(fā)的Base64編碼后的字符串將后面補位的=去掉了,導(dǎo)致iOS這邊調(diào)用系統(tǒng)的Base64解碼方法解不出來,而安卓和web端的方法進行了兼容。
三. 解決方法
根據(jù)Base64編碼編碼的原理(取3個8位的2進制,轉(zhuǎn)化為4個6位的2進制),編碼出來的字符串一定為4的倍數(shù),因此在解碼的時候,添加判斷,獲取到的字符串是否為4的整數(shù)倍,填充等號=,使其變?yōu)?的倍數(shù)。
方法如下:
// Base64解碼方法2
+ (NSString *)base64DecodingStringWithInputText:(NSString *)inputText {
NSInteger remainder = inputText.length % 4;
NSMutableString *tmpMstring = [[NSMutableString alloc] initWithString:inputText];
if (remainder > 0) {
for (; remainder < 4; remainder++) {
[tmpMstring appendString:@"="];
}
}
NSData *data = [[NSData alloc]initWithBase64EncodedString:tmpMstring options:0];
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}