Android端Encode问题
在安卓端,他们直接调用URLEncoder.encode(text, encodeType)
这样的函数来进行encode,可是他们这个函数对空格进行encode后,得到的是+号,而不是%20。我们看到在浏览器里空格是转换成%20的。另外,安卓这个API并不是对所有的特殊字符都进行转码,这样就有问题了…生成sign签名时,如果都encode了,那么结果就会不一样
iOS端Encode问题
在iOS端,我们直接使用系统NSString的API进行转码的话,不会对一些比较特殊的字符进行转码。系统NSString的转码API:
1
2
3
|
[
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,一切就可以解决了!
我想说的是,我遇到的问题,就是加密后上传的密码含有+号,但是服务端接收到的是空格,因此需要对加号进行单独处理,一般的UTF8转换是不能对特殊字符串进行转码的,用的还是上述方法哦!