文章地址
在 RFC 3986 文檔中規定,URL 中只允許包含以下四種:
- 英文字母 a-z 以及 A-Z
- 數字 0-9
- 4個特殊字符:中橫線 -、下劃線 _、小數點 . 以及波浪線 ~
- 保留字符:!*'();:@&=+$,/?#[]
除上述四種字符外,所有其他字符都將被替換成百分號 % + 兩位十六進制數。
@":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`\r\n\t" // @"" 是 OC 語法, 關注引號中字符即可
這33個字符需要轉義, 其中
@" \"#%&()+,/:;<>=?@\\|"
是特殊字符轉義編碼, 一定要轉義
@"{}^[]`~"
這些屬于不安全字段, 傳輸過程中某些網關會篡改這些字符, 最好也轉義
對于 NSURLComponents 不能解析的字符串有
@"[] \"<>%{}|\\^`\r\n\t"
這 16 個字符, 執行 urlComponents.queryItems 為 nil
特殊字符的編碼如下:
ASCII 字符 | URL-編碼 |
---|---|
空格 | %20 |
! | %21 |
" | %22 |
# | %23 |
$ | %24 |
% | %25 |
& | %26 |
' | %27 |
( | %28 |
) | %29 |
* | %2A |
+ | %2B |
, | %2C |
- | %2D |
. | %2E |
/ | %2F |
: | %3A |
; | %3B |
< | %3C |
= | %3D |
> | %3E |
? | %3F |
@ | %40 |
[ | %5B |
\ | %5C |
] | %5D |
^ | %5E |
_ | %5F |
` | %60 |
{ | %7B |
| | %7C |
} | %7D |
~ | %7E |
問題原由
在 url 解析參數時, 對 query 參數做了 [NSString stringByRemovingPercentEncoding]
轉義, 替換掉了所有的 %20 轉義字符, 然后將轉移后的 url 交給 WebView 展示. 然后 webview 在使用 NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:url];
解析 url 時, 發現 url 含有'^|'等字符就直接解析失敗, 造成 bug, 解決辦法也很簡單, 在解析失敗的時候, 針對
[] \"<>%{}|\\^`\r\n\t
這些字符做重新編碼, 然后再使用 NSURLComponents
解析即可, 代碼如下
NSString *specialString = @"[] \"<>%{}|\\^`\r\n\t";
NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:specialString] invertedSet];
NSString *encoded = [url stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
// 再解析 encoded 即可