記一次400錯誤引發的血案(URL中特殊符號的轉義/400 bad request錯誤)

來源:互聯網
上載者:User

標籤:request   mysq   空格   目錄   表單   出錯   配置   ddr   uri   

django+nginx+uwsgi部署的網站訪問某個URL時發生了400 bad request的錯誤,而使用django內建的開發版的web server時沒有遇到此問題。初步判斷是nginx或uwsgi配置問題。

網上有說是因為request header過大而nginx配置的client_header_buffer_size和large_client_header_buffers過小引起的,但就當前的狀態來看感覺不太可能。因為request header並不是特別大。至於是別的什麼原因還暫未找到,所以還是先試試看。

在nginx設定檔nginx.conf中的http部分加入如下兩行參數:
client_header_buffer_size 16k;
large_client_header_buffers 4 64k;
nginx預設會用client_header_buffer_size這個buffer來讀取header值,如果header過大,它會使用large_client_header_buffers來讀取header值。若該值設定過小而要求標頭/COOKIE過大則會報400 bad request錯誤。

調整參數重新載入設定檔重啟uwsgi後發現問題並未解決。
經仔細查看才發現原來是請求的URL中參數包含了特殊字元%,導致Web Server沒能夠正確解析出該URL,才報了這個錯誤。

在URL中下列字元具有特殊含義:
符號 含義     如何轉義
+     URL中+號表示空格                           %2B     
空格 URL中的空格可以用+號或者編碼 %20   
/   分隔目錄和子目錄                                 %2F       
?     分隔實際的URL和參數                     %3F       
%     指定特殊字元                                    %25       
#     表示書籤                                             %23       
&     URL中指定的參數間的分隔字元        %26       
=     URL中指定參數的值                        %3D 

比如sever端從提交的表單的輸入框中的值構造包含參數的URL,
若提交的內容為“pkgcr+awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%2Bawldb”,也即參數中q的值實際上為“pkgcr+awldb”
若提交的內容為“pkgcr awldb”,地址欄的URL顯示為“xxx/?q=pkgcr+awldb”,也即參數中q的值實際上為“pkgcr awldb”
若提交的內容為“pkgcr/awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%2Fawldb”,也即參數中q的值實際上為“pkgcr/awldb”
若提交的內容為“pkgcr?awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%3Fawldb”,也即參數中q的值實際上為“pkgcr?awldb”
若提交的內容為“pkgcr%awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%25awldb”,也即參數中q的值實際上為“pkgcr%awldb”
若提交的內容為“pkgcr#awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%23awldb”,也即參數中q的值實際上為“pkgcr#awldb”
若提交的內容為“pkgcr&awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%26awldb”,也即參數中q的值實際上為“pkgcr&awldb”
若提交的內容為“pkgcr=awldb”,地址欄的URL顯示為“xxx/?q=pkgcr%3Dawldb”,也即參數中q的值實際上為“pkgcr=awldb”

若要是直接在server端構造URL呢?比如server端的檔案中有個變數ip,值為“172.142.%”,要在server端構造一個URL供用戶端訪問,如“href=?ip={ip}&q=‘mysql‘”(此處假定{ip}是對變數的一種引用方式),那麼我們點擊這個連結會是什麼結果呢?

我們會看到,因為變數ip中包含特殊字元“%”,而“%”在URL中具有特殊含義,我們通過上述方式構造的URL相當於是“href=?ip=172.142.%&q=mysql”,web伺服器解析該URL時無法解釋%&從而導致出錯。同樣的原因,包含其他一些特殊字元時也會發生一些意想不到的問題,比如有另一個變數addr,值為“china&america”,構造的URL為“href=?addr={addr}&q=‘mysql’”,此時構建的URL相當於是“href=?addr=china&america&q=mysql”,web伺服器會把該URL中的第一個“&”後的“america”解析為另外一個參數而不是將“china&america”整體作為“addr”參數的值。

那麼如何在需要的時候在URL中包含諸如%、&、+、=等等這樣的特殊的字元呢?答案就是用相應的編碼代替特殊字元本身來構建URL。比如上例中可以先將ip的值替換為“172.142.%25”,將addr的值替換為“china%26america”,這樣構建出的URL分別為“href=?ip=172.142.%25&q=mysql”和“href=?addr=china%26america&q=‘mysql’”,這樣最終能夠將URL中的參數ip的值成功解析為“172.142.%”而將addr的值成功解析為china&america,而且不會引起其他參數解析混亂。

最終,發現是在訪問url的中文未進行轉碼導致的400錯誤。

ps: js中文轉碼(encodeURIComponent)

 

記一次400錯誤引發的血案(URL中特殊符號的轉義/400 bad request錯誤)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.