遇到个 Java 和 Php 在获取客户端 cookie 方式不一样致使跨系统的问题。因此写了这篇博客梳理下相关知识。php
实验
下面经过两个简单的实验,来看Java和Php在获取web请求中的cookie的不一样之处,我下面贴出http请求的相关信息,和服务端输出的结果。html
Java
请求信息git
服务端web
控制台输出api
Php
服务端数组
结果对比
发现Java
是不会对cookie
数据作任何处理,可是php
则会默认进行一次urldecode
操做,这致使了,两边系统里面获取同一cookie
时,结果不一致的 bug。浏览器
相似的问题 PHP 在解析外部变量时的一个 BUGcookie
Php 源码分析
主要查看两处源码app
咱们看到cookie的值会被执行php_url_decode
操做,下面附带其源码,且加上一段测试代码curl
上面php_url_decode
用到了php_htoi
,这个是由于urlencode
是按照rfc1738
对字符串中除了 -_. 以外的全部非字母数字字符都将被替换成百分号(%)后跟两位十六进制数。htoi
做用就是Converting Hexadecimal Digits Into Integers
。而后把计算出来的整型转换为char
,存回处理完以后的字符数组里。
小结
$_COOKIE
的数据在 php 这边是通过urldecode
的二手数据,这个致使和JAVA那边获取的cookie值不同了就。
编码扩展讨论
rawurlencode
与urlencode
的区别是什么?
手册上的解释是:
urlencode
返回字符串,此字符串中除了 -_. 以外的全部非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。此编码与 WWW 表单 POST 数据的编码方式是同样的,同时与 application/x-www-form-urlencoded 的媒体类型编码方式同样。因为历史缘由,此编码在将空格编码为加号(+)方面与 » RFC3986 编码(参见 rawurlencode())不一样。
经过源码能够看到就是对+
处理没有了。
请求的编码讨论
GET
当咱们在 url 传递+
的时候,浏览器不会默认为咱们执行urlencode
操做,可是 php 服务端取值的时候(仍是上面那段代码)会执行urldecode
,致使url中的+
被去掉。这一点也很是好检测。
POST
当咱们的作表单提交post
请求的时候,默认表单的编码规范就是application/x-www-form-urlencoded
,这样浏览器会自动的对咱们的数据就行一次urlencode
编码,以后 php 服务端收到$_POST
数据会再进行urldecode
。
当我在表单里提交了一段ab+cd
的内容,请求数据以下
服务端
输出结果
另外一种状况,若是咱们post的表单执行编码为multipart/form-data
,浏览器则不会对数据进行编码,服务端也不会对数据就行解码。
因此当咱们在配置 url 参数和 cookie 的时候,必定要注意url编码的问题。
本文做者:周梦康
本文为云栖社区原创内容,未经容许不得转载。