iOS/Android/Web Url Encode空格處理 原文連結:http://read01.com/3gDO.html

时间:2022-09-18 17:50:04

iOS/Android/Web Url Encode空格處理

原文連結:http://read01.com/3gDO.html

前言 這裡只是講一個故事,一個發生在我身上的真實的故事。曾經,我以為搞加密很簡單,不就是百度幾個加密演算法回來就可以了嗎?百度上一大堆呢,要什麼加密演算法都有,有什麼困難呢?是啊,理論上是可行的,可是,實際上卻有很多的坑,跳了一個又一個,最後才發現大家已經跳進坑裡面了。 這裡所講的故事是關於URL Encode的故事。想想我們iOS原來都是不管三七二十一,都是直接呼叫寫一個URLEncode方法,然後在加密時就encode一下,服務端decode一下就可以了,但是我們要防篡改,使用了sign… 在安卓端,他們直接呼叫URLEncoder.encode(text, encodeType)這樣的函數來進行encode,可是他們這個函數對空格進行encode後,得到的是+號,而不是%20。我們看到在瀏覽器裡空格是轉換成%20的。另外,安卓這個API並不是對所有的特殊字元都進行轉碼,這樣就有問題了…生成sign簽名時,如果都encode了,那麼結果就會不一樣 iOS端Encode問題 在iOS端,我們直接使用系統NSString的API進行轉碼的話,不會對一些比較特殊的字元進行轉碼。系統NSString的轉碼API: 123 [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 這樣並不對特殊的字元,像`、!、:等字元並不會轉碼,那怎麼辦呢?我們通常會自己寫一個API,呼叫C底層的API,可以指定對哪裡特殊字元也轉碼(給NSString擴充套件): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - (NSString *)hyb_URLEncode { NSString *newString = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR(":/?#@!$ &'*+,;="<>%{}|^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding))); if (newString) { return newString; } return self; } 贊助商 這樣就可以對所有特殊字元都轉碼了。而解碼則是非常簡單的,只是對空格進行特殊處理: 1 2 3 4 5 6 7 8 9 10 11 12 - (NSString *)hyb_URLDecode { NSString *input = self; NSMutableString *outputStr = [NSMutableString stringWithString:input]; [outputStr replaceOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [outputStr length])]; return [outputStr stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; } 在iOS端,對空格轉碼得到%20,對+轉碼得到%2b,但是在服務端和android端對空格轉碼得到的是+,而對+轉碼得到的也是%2b。問題就出在這裡了… 怎麼生成sign 通常的做法是對所有參數按key排序,然後拼接成a=x&b=y…這樣的字元串,然後md5一下。但是如果encode一下,iOS端和安卓端出現不同的結果,那麼服務端拿到以後是可以得到原串的,但是服務端encode一下所得到的結果會不一樣,那麼校驗sign就會失敗。 但是,如果不對每個value進行轉碼,在服務端就無法通過&來分割了,因為value中有&時,若不轉碼就會出問題,因此encode是必須的。 如何解決 生成sign時,是遍歷所有的key-value,然後拼接,最後md5。那麼,生成sign時,我們只要不對value進行encode,而其他上傳的參數值都encode,這樣就可以解決我們的問題了。 解決方案: 生成sign時,遍歷parameters,對每個value都不進行encode,直接拼接然後md5(前提是一定要Asc或者Desc排序一下)。 而其他參數在拼接時,就正常使用encode,一切就可以解決了!

原文連結:http://read01.com/3gDO.html