2

我有一个构建 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 字符串,因为它包含非 base 64 字符、两个以上的填充字符或填充字符中的非空白字符。

来自 url 的 id 参数“看起来”OK。问题似乎与失败的 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;
  }

任何建议将不胜感激。

4

3 回答 3

2

回顾一下,我正在创建一个使用 base-64 编码参数的 URL,该参数本身就是一个三重 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 - 维基百科

MyTenPennies Base-32 .NET 实现

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

希望这可以帮助。

于 2012-08-08T08:05:48.383 回答
1

看起来你真的很亲近。您的encyrpted.EncodeBase64()函数返回了一个额外的零。

试试这个:

string data = "H3uKbdyzrUo=";
string b64str = Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(data));
string clearText = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(b64str));
于 2012-08-07T14:12:59.643 回答
0

这是一个有趣的问题。我的猜测是 IE 6 正在吃掉一些字符。

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

但是,如果您要填充该字符串,直到它的长度是四的倍数(“ywhar0xznxpjdnfnddc0yxzbk2jnqt090”+“a12”),那么就可以了。

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

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

于 2012-08-07T14:25:06.033 回答