无法解码Base-64 URL

时间:2012-08-06 13:03:51

标签: asp.net-mvc base64 url-encoding

我有一个构建HTML电子邮件的应用程序。内容中包含编码的URL参数,该参数可能包含促销代码或产品参考。该电子邮件由Windows服务(实质上是控制台应用程序)生成,单击时链接由MVC网站处理。以下是创建电子邮件链接的代码:

string CreateLink(string domain, string code) {
    // code == "xyz123"
    string encrypted = DES3Crypto.Encrypt(code);  // H3uKbdyzrUo=
    string urlParam = encrypted.EncodeBase64();   // SDN1S2JkeXpyVW890
    return domain + "/" + urlParam;
}

MVC控制器上的action方法构造如下:

public ActionResult Index(string id) {
    string decoded = id.DecodeBase64();
    string decrypted = DES3Crypto.Decrypt(decoded);
    ...
}

在我们所有的测试中,这个机制已按预期工作,但是,现在我们已经上线,我们看到大约4%的错误率,其中base-64的转换失败,但有以下异常:

输入不是有效的Base-64字符串,因为它包含非基本64个字符,两个以上的填充字符或填充字符中的非空白字符。

来自网址的id参数'看起来'确定。问题出现在EncodeBase64 / DecodeBase64方法失败,因为DecodeBase64方法在失败时返回“乱码”字符串,例如“ nl □ 7y b 8 sJ =”链接。

此外,大多数错误来自IE6用户代理,导致我认为这是一个字符编码问题,但我不明白为什么。

供参考,以下是我的base-64 URL编码的代码:

  public static string EncodeBase64(this string source)
  {
     byte[] bytes = Encoding.UTF8.GetBytes(source);
     string encodedString = HttpServerUtility.UrlTokenEncode(bytes);
     return encodedString;
  }

  public static string DecodeBase64(this string encodedString)
  {
     byte[] bytes = HttpServerUtility.UrlTokenDecode(encodedString);
     string decodedString = Encoding.UTF8.GetString(bytes);
     return decodedString;
  }

非常感谢任何建议。

3 个答案:

答案 0 :(得分:2)

回顾一下,我正在创建一个使用base-64编码参数的URL,该参数本身就是一个Triple DES加密字符串。所以URL看起来像http:// [Domain_Name] / SDN1S2JkeXpyVW890该链接引用了MVC网站上的控制器操作。

然后将URL插入HTML格式的电子邮件中。查看错误日志,我们看到响应该链接的大约5%的公共用户正在抛出“无效的base-64字符串错误”。这些错误中的大多数(但不是全部)都与IE6用户代理有关。

在尝试了许多基于字符和URL编码的可能解决方案后,发现在客户端进程的某个地方,url被转换为小写 - 当然,这打破了base-64编码(因为它是使用的)大写和小写编码字符)。

案件损坏是否是由客户端的浏览器,电子邮件客户端或本地防病毒软件引起的,我无法确定。

解决方案 不要使用任何标准的base-64编码方法,而是使用base-32或zBase-32编码 - 两者都不区分大小写。

有关详细信息,请参阅以下链接

Base-32 - Wikipedia

MyTenPennies Base-32 .NET Implementation

故事的寓意是,在某些公共环境中,Base-64 URL编码可能不可靠。 Base-32虽然稍微冗长,但是更好的选择。

希望这有帮助。

答案 1 :(得分:1)

看起来你真的很亲密。你的encyrpted.EncodeBase64()函数有一个额外的零点。

试试这个:

string data = "H3uKbdyzrUo=";
string b64str = Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(data));
string clearText = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(b64str));

答案 2 :(得分:0)

这是一个有趣的问题。我的猜测是IE 6正在吃一些角色。

例如,您包含的字符串“ywhar0xznxpjdnfnddc0yxzbk2jnqt090”的长度不是四的倍数(这是FromBase64工作的必要条件http://msdn.microsoft.com/en-us/library/system.convert.frombase64string.aspx

但是如果你要填充那个字符串直到它的长度是四的倍数(“ywhar0xznxpjdnfnddc0yxzbk2jnqt090”+“a12”)那么那就行了。

MSDN文档说一个(“=”)或两个(“==”)相等的字符用于填充/ fromBase64方法,我怀疑IE 6正在从你发送的字符串中截断它。

这是完全的猜测,但我希望它有所帮助。