遇到個 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編碼的問題。
本文做者:周夢康
本文爲雲棲社區原創內容,未經容許不得轉載。