2010-05-27 70 views
57

正如標題無效長度說,我得到:對於BASE-64字符數組

無效長度爲一個基地-64炭 陣列。

我已閱讀關於這個問題在這裏,似乎 建議是存儲ViewState在SQL中,如果它很大。我是 使用了一個具有大量數據收集的嚮導,因此我的ViewState的機會很大 很大。但是,在我轉向「店內數據庫」 解決方案之前,也許有人可以看看並告訴我我是否有其他選項 ?

public void SendEmailAddressVerificationEmail(string userName, string to) 
{ 
    string msg = "Please click on the link below or paste it into a browser to verify your email account.<BR><BR>" + 
        "<a href=\"" + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + 
        userName.Encrypt("verify") + "\">" + 
        _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + 
        userName.Encrypt("verify") + "</a>"; 

    SendEmail(to, "", "", "Account created! Email verification required.", msg); 
} 

的加密方法是這樣的:

public static string Encrypt(string clearText, string Password) 
{ 

    byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText); 

    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 


    byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16)); 

    return Convert.ToBase64String(encryptedData); 
} 

下面是HTML的樣子Hotmail中:

我使用下面的方法構建的電子郵件交付

請點擊下面的鏈接或 將其粘貼到瀏覽器以驗證您的 電子郵件帳戶。

http://localhost:1563/Accounts/VerifyEmail.aspx?a=YOHY57xYRENEOu3H+FGq1Rf09AZAI56EPjfwuK8XWKg=

在接收端,VerifyEmail.aspx.cs頁面有一行:

string username = Cryptography.Decrypt(_webContext.UserNameToVerify, "verify"); 

這裏是UserNameToVerify吸氣:

public string UserNameToVerify 
{ 
    get 
    { 
     return GetQueryStringValue("a").ToString(); 
    } 
} 

這裏是GetQueryStringValue方法:

private static string GetQueryStringValue(string key) 
{ 
    return HttpContext.Current.Request.QueryString.Get(key); 
} 

和解密方法是這樣的:

public static string Decrypt(string cipherText, string password) 
{ 

    **// THE ERROR IS THROWN HERE!!** 
    byte[] cipherBytes = Convert.FromBase64String(cipherText); 

可這個錯誤可以用一個代碼修復補救或我必須存儲ViewState的數據庫?

+2

PLZ發送我TEH誤差 – DevDemon 2010-05-27 23:37:36

+0

DevDemon - 作爲張貼的誤差「出現FormatException:用於基本-64字符數組長度無效」。還有什麼我應該送? – 2010-05-27 23:55:04

回答

127

base64編碼字符串的長度始終是4的倍數。如果不是4的倍數,那麼=字符直到它結束。 ?name=value形式的查詢字符串在value包含=字符(其中一些將被刪除,我不記得確切的行爲)時會出現問題。在進行base64解碼之前,您可能能夠脫離附加正確數量的=個字符。

編輯1

您可能會發現的UserNameToVerify值已"+"的改變" "的,所以你可能需要做一些事情,像這樣:

a = a.Replace(" ", "+"); 

這應該得到的長度對;

int mod4 = a.Length % 4; 
if (mod4 > 0) 
{ 
    a += new string('=', 4 - mod4); 
} 

過程調用UrlEncode(如LukeH的答案)應使這一切毫無意義。

+8

感謝布拉德 - 它實際上是這樣做的一小部分代碼:a = a.Replace(「」,「+」); – 2010-05-28 07:46:42

+1

@Code Sherpa:如果是這樣的話,您最好的選擇是在發送之前urlencode字符串和urldecode。否則,如果另一個url重要字符進入你的字符串,那麼你將不得不添加另一個'Replace'語句,編碼是一種套裝,無論如何都可以保護你。 – 2010-10-20 10:57:49

+0

完全工作我。這是解決方案的傢伙。 – tugberk 2011-03-02 15:25:33

4

我不知道數據的初步猜測是UserNameToVerify的長度不是4的倍數。查看msdn上的FromBase64String

// Ok 
byte[] b1 = Convert.FromBase64String("CoolDude"); 
// Exception 
byte[] b2 = Convert.FromBase64String("MyMan"); 
+0

謝謝SwDevMan81。剛剛離開工作,但今晚晚些時候會嘗試。謝謝你的幫助。 – 2010-05-27 23:51:36

+0

沒問題,修復的方法是用一個字符填充以獲得4的倍數的字符串。 – SwDevMan81 2010-05-27 23:53:06

+0

再次感謝SwDevMan81。我會看看這個。我在我的原始文章(FYI)中發佈了UserNameToVeryify。好...現在我真的需要走了,否則我會與真正的老闆陷入困境:) – 2010-05-28 00:04:24

23

我的猜測是,你只需要URL-encode您的Base64編碼字符串,當你將其包含在查詢字符串。

Base64編碼使用一些字符,如果它們是查詢字符串的一部分(即+/,也可能是=),則必須對其進行編碼。如果字符串編碼不正確,那麼您將無法在另一端成功解碼,因此會出現錯誤。

可以使用HttpUtility.UrlEncode方法來編碼您的Base64編碼字符串:

string msg = "Please click on the link below or paste it into a browser " 
      + "to verify your email account.<br /><br /><a href=\"" 
      + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" 
      + HttpUtility.UrlEncode(userName.Encrypt("verify")) + "\">" 
      + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" 
      + HttpUtility.UrlEncode(userName.Encrypt("verify")) + "</a>"; 
+0

謝謝。剛剛嘗試過你的建議盧克,但沒有工作:(。 – 2010-05-27 23:49:25

+0

@Sherpa - 繼續工作,問題幾乎可以肯定與尾隨的'='字符 – 2010-05-27 23:53:25

+0

盧克 - 我有一種感覺,你是對的。在FY1中 - 我在我的原始文章中添加了我的Hotmail收件箱中字符串的樣子 – 2010-05-27 23:59:18

7

我並沒有足夠的知名度或評論,但LukeH的回答是對我來說的。由於AES加密是現在使用的標準,它會生成一個base64字符串(至少是我見過的所有加密/解密實現)。這個字符串的長度是4的倍數(string.length%4 = 0)

我得到的字符串包含+和=開始或結束,並且當您將它連接到URL的查詢字符串時,它會看起來是正確的(例如,在您生成的電子郵件中),但是當鏈接被遵循並且.NET頁面接收並將其放入this.Page.Request.QueryString時,那些特殊字符將會消失,並且您的字符串長度將會不是4的倍數。

由於字符串的前部是特殊字符(例如:+),以及=在最後,您不能只添加一些=來彌補差異因爲您正在以與原始查詢字符串中實際不匹配的方式更改密碼文本。

因此,使用HttpUtility.URLEncode(而不是HtmlEncode)封裝密碼文本會以一種確保.NET在將其解析爲查詢字符串集合時將其解析爲原始狀態的方式轉換非字母數字字符。

好處是,我們只需要在生成URL的查詢字符串時執行URLEncode。在傳入方面,它會自動轉換回原始字符串值。

下面是一些示例代碼

string cryptostring = MyAESEncrypt(MySecretString); 
string URL = WebFunctions.ToAbsoluteUrl("~/ResetPassword.aspx?RPC=" + HttpUtility.UrlEncode(cryptostring));