如何於MVC/Web API路由中傳送Base64編碼

如何於MVC/Web API路由中傳送Base64編碼

base64
from technet.microsoft.com

之前提到過如何使用路由傳遞含"+"符號到ASP.NET Web API 2有二種方式,一是使用QueryString,一是修改allowDoubleEscaping,不過allowDoubleEscaping的修改會降低系統安全性,是個不得以的選項。重覆的問題又活生生出現在面前,只是這一次必須把這個含+符號的值放在路由中。怎麼辦?有無更好的方式解決這個問題呢?

+號+號你為什麼會出現

首先,第一次處理如何使用路由傳遞含"+"符號到ASP.NET Web API 2問題時,那是一段對稱加密的程式,因為是中間接手處理,沒有細看實作細節,我們以DESCryptoServiceProvider (DES 的實作)為例來說明:

 private string Encryption(string plainText)                
 {                                                                      
     if (plainText == null || plainText.Length <= 0)                    
         throw new ArgumentNullException("cipherText");

     byte[] b = Encoding.UTF8.GetBytes(plainText);                      
     DESCryptoServiceProvider des = new DESCryptoServiceProvider();     
     ICryptoTransform ict = des.CreateEncryptor(des.Key, des.IV);               
     byte[] desData = ict.TransformFinalBlock(b, 0, b.Length);
                                                                        
     return Convert.ToBase64String(desData);                            
 }                                                                       
 
DES加密程式

看出問題點了嗎?

我們先看看這個的字串如果使用在路由上會產生什麼問題,以/{controller}/{action}/{id}路由為例:/home/index/EZ7+/+wvla4=,怎麼+號(加號)都還沒處理就馬上出事了?

看的出來了嗎?

有在寫MVC或Web API的人,第二個問題很直覺就能看出來了,多了一個「/」符號,此時就算設置allowDoubleEscaping讓路由能正常處理+號,id透過ModelBinding後還是不正常的。

回到問題一,看出問題了嗎?

Base64

問題在我們把加密的結果使用Base64編碼轉換並進行回傳,用URL傳送Base64編碼會碰到一些問題,看看Base64編碼使用的符號:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/。黑大的討論是把Base64編碼放在QueryString之中的解決辦法。還是無法解決我需要把Base64編碼值放在路由中的需求。

用於URL的改進Base64編碼

原來解決方式早已經列在wiki的文章之中,以下引述自wiki:

然而,標準的Base64並不適合直接放在URL裡傳輸,因為URL編碼器會把標準Base64中的「/」和「+」字符變為形如「%XX」的形式,而這些「%」號在存入數據庫時還需要再進行轉換,因為ANSI SQL中已將「%」號用作通配符。

為解決此問題,可採用一種用於URL的改進Base64編碼,它不在末尾填充'='號,並將標準Base64中的「+」和「/」分別改成了「-」和「_」,這樣就免去了在URL編解碼和數據庫存儲時所要作的轉換,避免了編碼信息長度在此過程中的增加,並統一了數據庫、表單等處對象標識符的格式。

簡言之,找兩個非+、/、=的符號來Replace即可。依照wiki的說明,我們實作以下程式碼:

 public static class UrlBase64                                            
 {                                             
     public static string ToUrlReplace(string base64String)               
     {                                                                    
         return base64String.Replace("+", "-").Replace("/", "_");         
     }                                                                    
                                             
     public static string FromUrlReplace(string base64String)             
     {                                                                    
         return base64String.Replace("-", "+").Replace("_", "/");         
     }                                                                    
 }                                                                         
 

加密回傳之前把+/給取代,解密之前則反向給取代回來。

用於URL的改進Base64編碼

這樣取代之後,不論是QueryString或使用在路由(Route)上都不會再發生+或\符號造成的問題。

有時候我們真的會把問題給複雜化,剛碰時只會想要不要用Base64編碼,不用的話怎麼辦?明明就是一個簡單的取代(Replace)動作就可以解決的事。

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。