首先了解以下中文字符在使用urlencode的时候运用的基本原理:
urlencode()函数原理就是首先把中文字符转换为十六进制,然后在每个字符前面加一个标识符%。
此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。
在做通过关键词查询条目的需求时,发现前端IOS传过来的“中文关键字”是通过url编码的字串,直接使用,我们是是用不了的,拿php为例,我们需要对该值使用urldecode()函数进行解码,解码后就会是对应的中文了。当时觉得很纳闷,为什么前端要对参数编码后传给后台,心里的答案时为了安全起见,防止别人截取url后对其中的参数进行解析。但是,总感觉好模棱两可,既然我后台可以解码出正确值,为什么截取了你url的人不可以呢,如此哪来的安全可言。
于是,我就问了问之前工作的ios的同事,结果,他斩钉截铁的告诉我,就是为了安全,我差点就以为就真的是这样了,不过还好我内心的强烈不同意与好奇心,在网上查了又查,于是,下面就是我得出的结论:
以iOS编程为例,每当我们从服务器获得到一个链接需要分析链接的组成,或者在捕捉本地网路请求作出响应判断的时候,我们经常需要对URL进行解码和编码。那么为什么要进行解码和编码呢。
比如有一个需求,你需要截取webveiw请求来实现一些操作。那么此时我们就需要从请求到的url中获取一些参数。
url:www.baidu.com?canshu1=zhi1&canshu2=zhi2
我们从url中获取参数值的方法是从=后获取值,针对这个链接,我们从链接中获取参数。有两种情况
1.参数有两个canshi1,canshu2,值分别是zhi1和zhi2
2.参数只有一个canshu1, 值为zhi1&canshu2=zhi2
显然造成了歧义。
为了避免歧义,我们需要就必须要讲值中的“=”或者“&”等特殊符号用其他符号代替,防止对=后面取值的方式造成影响,这个代替过程就是编码。
以情况2为例子,此处有一个参数canshu1,其值是“zhi1&canshu2=zhi2”,进行URL的utf8编码后得到zhi1%26canshu2%3Dzhi2,将编码后的值放入链接
www.baidu.com?canshu1=zhi1%26canshu2%3Dzhi2
于是拿到编码后链接的人解析,就直接取=后面的值作为canshu1的值,得到值为zhi1%26canshu2%3Dzhi2,然后对“zhi1%26canshu2%3Dzhi2”进行解码(需要用和编码同样的方式,一般有UTF8和gb2312)得到值“zhi1&canshu2=zhi2”,完全正确。
注意:如果值中有%26则也会被转化成%2626也不会造成歧义。
1、为什么要编码
网络标准RFC 1738规定url中只能包含英文字母和阿拉伯数字,以及一些特殊字符:
"...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."
“只有字母和数字[0-9a-zA-Z]、和特殊符号”$-_.+!*’(),”[不包括双引号]、及某些保留字,才可以不经过编码直接用于URL。”
此时如果url中包含如汉字或者其他特殊字符则需要对它进行编码,编码的意义在于,假如url的参数中的中文或特殊字符在发送到服务端时,服务端无法解析它的真正意义,会导致服务端不能理解客户端的请求。
如:
url中的保留字?
表示后面连接的是一些请求参数,而参数中如果也包含?
,服务端就不知道从哪个?
之后是参数;
url中的保留字&
用来连接并列的参数项,参数中包含&
时,服务端依然无法判断。
2、转码范围
-
ASCII 的控制字符
这些字符都是不可打印的,自然需要进行转化。
-
一些非ASCII字符
这些字符自然是非法的字符范围。转化也是理所当然的了。
-
一些保留字符
很明显最常见的就是“&”了,这个如果出现在url中了,那你认为是url中的一个字符呢,还是特殊的参数分割用的呢?
-
就是一些不安全的字符了。
例如:空格。为了防止引起歧义,需要被转化为“+”。
转自:http://blog.csdn.net/andanlan/article/details/53368727