导致此“Base-64 字符数组的长度无效”的原因

Posted

技术标签:

【中文标题】导致此“Base-64 字符数组的长度无效”的原因【英文标题】:What causing this "Invalid length for a Base-64 char array" 【发布时间】:2010-10-25 22:01:29 【问题描述】:

我在这里几乎没有什么可做的。我无法在本地重现此内容,但是当用户收到错误消息时,我会收到自动电子邮件异常通知:

Invalid length for a Base-64 char array.

  at System.Convert.FromBase64String(String s)
  at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
  at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState)
  at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState)
  at System.Web.UI.HiddenFieldPageStatePersister.Load()

我倾向于认为分配给视图状态的数据存在问题。 例如:

List<int> SelectedActionIDList = GetSelectedActionIDList();
ViewState["_SelectedActionIDList"] = SelectedActionIDList;

如果不能在本地重现错误,很难猜测错误的来源。

如果有人遇到过这个错误,我真的很想知道你发现了什么。

【问题讨论】:

【参考方案1】:

在 urlDecode 处理文本后,它将所有 '+' 字符替换为 ' ' ...因此出现错误。您应该简单地调用此语句以使其再次兼容 base 64:

        sEncryptedString = sEncryptedString.Replace(' ', '+');

【讨论】:

好东西。谢谢。我正在从一个 C++ MFC 应用程序调用一个 ASP.NET Web 服务,并且在已经花费了几个小时之后,我可能已经在许多方向上分支尝试解决这个问题。你刚刚为我节省了很多时间。 刚刚遇到这个问题,正如你所说的那样,它是空格,替换为+ 修复了它。英雄! 任何人都可以就在哪里包含此代码提供指导吗?我经常处理这个问题,但是从代码 sn-p 中,我无法确定在哪里实施修复。 @dst3p 在处理管道中遇到错误的任何地方使用它。检查您的堆栈跟踪并查看导致错误的方法。【参考方案2】:

我已经看到这个错误是由适当大小的视图状态和过度激进的内容过滤设备/防火墙(尤其是在与 K-12 教育机构打交道时)相结合引起的。

我们通过在 SQL Server 中存储 Viewstate 来解决这个问题。在走这条路之前,我建议您尝试限制您对视图状态的使用,方法是不要在其中存储任何大的东西,并为所有不需要它的控件关闭它。

在 SQL Server 中存储 ViewState 的参考:MSDN - Overview of PageStatePersisterASP Alliance - Simple method to store viewstate in SQL ServerCode Project - ViewState Provider Model

【讨论】:

我复制了页面的视图状态并将其粘贴到 Word 中。它的长度超过 86000 个字符。这似乎太多了。 哎呀,我现在遇到了问题。我已尽可能关闭所有控件的 ViewState。我正在使用具有多个页面和大量内容的向导控件。有什么建议吗? @Mike C.,这是一个非常令人沮丧的问题!您可以将向导的每个页面的内容分解为用户控件并按需加载内容(通过 ajax?)。当然,这只是针对那个页面的一种解决方案,如果您开始在一致的基础上遇到问题,您可能需要考虑将视图状态存储在您的数据库中。我已经用在 SQL Server 中存储视图状态的参考更新了我的答案。 我遇到的另一个问题是超过 86000 个字符长(我认为实际上可能接近 85K,假设是单字节字符)是您的 .NET 应用程序也可能开始将视图状态字符串放在如果应用程序池没有被回收,大对象堆可能会随着时间的推移导致堆碎片(最终导致 OutOfMemoryException)。 我也遇到了同样的问题,请问如何解决这个问题。【参考方案3】:

我的猜测是编码或解码过于频繁 - 或者您的文本中有多行。

Base64 字符串的长度必须是 4 个字符的倍数 - 每 4 个字符代表 3 个字节的输入数据。不知何故,由 ASP.NET 传回的视图状态数据已损坏 - 长度不是 4 的倍数。

发生这种情况时,您是否记录用户代理?我想知道它是否是某个地方表现不佳的浏览器......另一种可能性是有一个代理在做淘气的事情。同样尝试记录请求的内容长度,以便您查看它是否仅发生在大型请求中。

【讨论】:

在我的情况下,浏览器始终是 Safari,无论是移动版还是桌面版【参考方案4】:

试试这个:

public string EncodeBase64(string data)

    string s = data.Trim().Replace(" ", "+");
    if (s.Length % 4 > 0)
        s = s.PadRight(s.Length + 4 - s.Length % 4, '=');
    return Encoding.UTF8.GetString(Convert.FromBase64String(s));

【讨论】:

此方法有助于解决问题。虽然我没有使用UTF8编码【参考方案5】:
int len = qs.Length % 4;
            if (len > 0) qs = qs.PadRight(qs.Length + (4 - len), '=');

qs 是任何 base64 编码的字符串

【讨论】:

【参考方案6】:

正如其他人所提到的,当某些防火墙和代理阻止访问包含大量 ViewState 数据的页面时,可能会导致这种情况。

ASP.NET 2.0 引入了ViewState Chunking mechanism,它将 ViewState 分解为可管理的块,从而允许 ViewState 毫无问题地通过代理/防火墙。

要启用此功能,只需将以下行添加到您的 web.config 文件中。

<pages maxPageStateFieldLength="4000">

这应该用作减小 ViewState 大小的替代方法,但它可以有效地防止由于激进的代理和喜欢。

【讨论】:

会有副作用吗? 我没有观察到,more information on viewstate 那么您的最佳长度是多少?我确实将它设置为 1024【参考方案7】:

很遗憾,这不是答案。在遇到间歇性错误一段时间后,我终于恼火地尝试修复它,但我还没有找到修复方法。但是,我已经确定了重现我的问题的方法,这可能对其他人有所帮助。

在我的情况下,这只是一个本地主机问题,在我的开发机器上也有应用程序的数据库。这是我正在使用 VS2005 编辑的 .NET 2.0 应用程序。 Win7 64位机也安装了VS2008和.NET 3.5。

以下是会产生错误的各种形式:

    加载表单的新副本。 输入一些数据,和/或使用任何表单控件回发。只要没有明显的延迟,请重复所有您喜欢的内容,并且不会出现错误。 稍等片刻(可能需要 1 或 2 分钟,不超过 5 分钟),然后再尝试回发。

延迟一两分钟“等待本地主机”,然后浏览器“重置连接”,global.asax 的应用程序错误陷阱日志:

Application_Error event: Invalid length for a Base-64 char array.
Stack Trace:
     at System.Convert.FromBase64String(String s)
     at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
     at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState)
     at System.Web.UI.HiddenFieldPageStatePersister.Load()

在这种情况下,它不是视图状态的 SIZE,而是与页面和/或视图状态缓存有关的东西,这似乎在咬我。在Web.config 中设置&lt;pages&gt; 参数enableEventValidation="false"viewStateEncryption="Never" 并没有改变行为。也没有将maxPageStateFieldLength 设置为适度的值。

【讨论】:

【参考方案8】:

看看你的 HttpHandlers。在我实施压缩工具(来自 Telerik 的 RadCompression)后的几个月里,我一直注意到一些奇怪且完全随机的错误。我注意到以下错误:

System.Web.HttpException:无法验证数据。

System.Web.HttpException:客户端断开连接。---> System.Web.UI.ViewStateException:无效的视图状态。

System.FormatException:Base-64 字符数组的长度无效。

System.Web.HttpException:客户端已断开连接。 ---> System.Web.UI.ViewStateException: 无效的视图状态。

我在我的博客上wrote about this。

【讨论】:

您的博客已关闭。你有另一个链接或者你可以发布相关信息吗?谢谢 web.archive.org/web/20111015131130/http://…【参考方案9】:

这是因为视图状态很大,就我而言,我很幸运,因为我没有使用视图状态。我刚刚在表单标签上添加了enableviewstate="false",视图状态从 35k 变为 100 个字符

【讨论】:

【参考方案10】:

在使用 SqlMembershipProvider 对 Membership.ValidateUser 进行初始测试期间,我将哈希 (SHA1) 算法与盐结合使用,如果我将盐长度更改为不能被四整除的长度,我会收到此错误。

我没有尝试过上述任何修复,但如果更改了盐,这可能有助于某人查明这是此特定错误的根源。

【讨论】:

【参考方案11】:

正如 Jon Skeet 所说,字符串必须是 4 个字节的倍数。但我仍然收到错误消息。

至少它在调试模式下被删除了。在Convert.FromBase64String() 上放置一个断点,然后单步执行代码。奇迹般地,错误对我来说消失了 :) 它可能与其他人报告的视图状态和类似的其他问题有关。

【讨论】:

【参考方案12】:

除了对我有帮助的 @jalchr's solution 之外,我发现当从 c++ 应用程序调用 ATL::Base64Encode 以对传递给 ASP.NET Web 服务的内容进行编码时,您还需要其他东西。除了

sEncryptedString = sEncryptedString.Replace(' ', '+'); 

来自@jalchr's solution,你需要确保你不要在ATL::Base64Encode上使用ATL_BASE64_FLAG_NOPAD标志:

 BOOL bEncoded = Base64Encode(lpBuffer,
                    nBufferSizeInBytes,
                    strBase64Encoded.GetBufferSetLength(base64Length),
                    &base64Length,ATL_BASE64_FLAG_NOCRLF/*|ATL_BASE64_FLAG_NOPAD*/);

【讨论】:

以上是关于导致此“Base-64 字符数组的长度无效”的原因的主要内容,如果未能解决你的问题,请参考以下文章

核心数据“数据库出现损坏”——导致此错误的原因是啥?

错误 1064:显示语法错误无法找到导致此错误的原因

导致此错误的原因 - “致命错误:无法找到本地咕噜声”

导致此问题的原因:无法从 switch 语句跳转到此案例标签 [重复]

什么原因导致“Google Maps API 服务器拒绝了您的请求。发现此 API 项目的内部错误。”?

查找此异常原因的下一步是啥?