問題背景接收客戶端傳入引數,base64解碼失敗,經過排查發現原因是引數上傳前字串中有+,但是php接收後,發現+變成了空格,導致base64解碼失敗。
測試驗證
訪問乙個測試的介面 /internal/test
curl ''
1驗證1:
簡單輸出
$_get
public
function
test() 12
3結果:
array(1) 12
34結論:可以看到直接接收get引數,+變成了空格
+變成空格的原因
經過一頓查資料,首先我們要知道url編碼是什麼
url編碼
乙個例子
我們常見的乙個url,例如csdn搜尋功能的乙個url(https://
so.csdn.net/so/search/s.do?q=php基於字典樹演算法實現搜尋聯想功能&t=&u=),當你從瀏覽器中複製出來的時候,這個url長下面這樣子
這就是url被編碼了,這裡編碼是將中文轉換成了%開頭的兩個十六進製制數。
為什麼url會被編碼呢?
url中的引數部分是由乙個個key=value的引數對組成,而如果&=/?等在url具有一定功能的特殊字元出現在key或者value中時,就會導致語義出現不一致的情況,例如引數q的值是a&b,那麼當出現q=a&b&f=s這樣乙個引數對時,是表示q的值是a&b,還是q的值是a,而b的值為空呢?
因此需要對url進行編碼,這樣被編碼過的字元就不再會有歧義,上面例子中的q=a&b&f=s會被編碼成q=a%26b&f=s,你看這樣是不是就不會混亂了。
如何對url進行編碼呢?
url如何進行編碼由rfc標準進行規定,
在rfc-1738對url進行說明的各項標準中,提出了要對url中不安全的字元進行編碼,編碼方式即使用%和緊跟的兩個十六進製制數字表示,注意在該標準中空格被編碼成+在公升級版rfc-2396對uri進行說明的各項標準中,再次提到了對引數進行編碼,注意在在該標準中空格被編碼成%20在再次公升級版的rfc-3986標準中,對url的編譯碼問題做出了更加詳細的建議,指出了哪些字元需要被編碼才不會引起url語義的轉變,以及對為什麼這些字元需要編碼做出了相應的解釋。
回頭來研究下一開始的問題
通過以上的資料,我們可以看出來+被變成了空格的原因,正是按照rfc-1738標準進行的反編碼,也就是.php接收$_get引數遵循的是的是rfc-1738標準。
所以直接讀取
$_get時,+就反過來被解碼成了空格
怎麼解決這個問題
那我們怎麼讓php不按照rfc-1738標準進行解碼,而是按照公升級版的rfc-3986標準進行解碼呢?
最簡單的辦法當然是讓+以正確的方式進行編碼,也就是在客戶端請求介面時,按照rfc-3986標準進行對url進行編碼。此時+被編碼成%2b,當php接收引數時,將%2b解碼成+,大功告成。
驗證結果
對url進行正確的編碼
curl ''
1此時可以看到介面輸出
array(1) 12
345php語言裡還有別的坑嗎?
除了接收
$_get引數外
,php中還有對url引數處理的兩個常用的函式urlencode和urldecode。
注意這兩個函式也是遵循rfc-1738進行編碼和解碼,從官網的說明可以看到
this differs from the » rfc 3986 encoding (see rawurlencode()) in that for historical reasons, spaces are encoded as plus (+) signs.做個試驗
先對字串abc def進行編碼
$str = 'abc def';
echo
urlencode($str);1
2輸出結果
abc+def
1然後對字串a=abc+def進行解碼
$str = 'a=abc+def';
echo
urldecode($str);1
2輸出結果
a=abc def
1可以看出確實空格被編碼成了+,而+則被解碼成空格
怎麼解決呢?
那php裡面有沒有使用rfc-3986標準進行編碼的呢,有的,是rawurlencode和rawurldecode,php官方是這麼寫的
rawurlencode — url-encode according to rfc 3986再來做個試驗
先對字串abc def進行編碼
$str = 'abc def';
echo
rawurlencode($str);1
2輸出結果
abc%20def
1可以看到空格被編碼成%20,然後對字串a=abc+def進行解碼
$str = 'a=abc+def';
echo
rawurldecode($str);1
2輸出結果
a=abc+def
1可以看到+解碼後還是+,沒有變成空格
結論所以最符合標準,並且比較容易實現的方案就是讓客戶端or前端在請求服務端介面時遵循rfc-3986標準進行正確的url編碼
SQL裡面有樂子
1 oracle的with應用場景 2 connect by的簡單示例 3 dual表與rownum的威力 4 oracle中的隱式資料型別轉換 5 sql效能的優化簡單策略 6 關鍵有的例子挺有樂子哦 sql語言主要操作增刪改,但是內部機理卻是非常複雜。在使用sql語言的發燒友裡,往往會有一句sq...
postman裡面的mockserver使用方法
首先說下mockserver是幹啥的,從英文翻譯理解就是模擬乙個伺服器,通俗點說就是給你針對某個特定的介面,返回你自定義的返回值的工具,筆者是經常用在客戶端對後台資料驗證的模擬上,非常方便。下面看下postman的使用步驟 上圖是postman儲存的介面,這裡拿之前練習django的專案演示,要說明...
笑話裡面有年味兒
1 近一年吧,拼命攢加借房子首付,吃的可謂慘不忍睹,這不過年了麼,和老婆提議咱們吃點好的?老婆想了想說 咱們加個菜,再加個魚吧。瞬間感動,只見老婆回身冰箱裡取出一袋魚泉榨菜 2 過年了,老婆給我1000元壓歲錢。我按照中國的傳統習俗虛讓了一下,僅僅一下。老婆竟然收回去了,還說不要拉倒,明年再說 到手...