代码之家  ›  专栏  ›  技术社区  ›  Neilski

无法解码Base-64 URL

  •  2
  • Neilski  · 技术社区  · 12 年前

    我有一个构建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控制器上的动作方法构造如下:

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

    在我们所有的测试中,这种机制都如预期的那样工作,然而,现在我们已经上线了,我们看到大约4%的错误率,从base-64转换失败,但以下例外:

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

    url中的id参数“看起来”正常。问题似乎是EncodeBase64/DecodeBase64方法失败,因为DecodeBase64方法在失败的链接上返回“乱码”字符串,如“nl7yb8sJ=”。

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

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

      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 回复  |  直到 6 年前
        1
  •  2
  •   Neilski    12 年前

    概括一下,我创建了一个使用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 - Wikipedia

    MyTenPennies Base-32 .NET Implementation

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

    希望这能有所帮助。

        2
  •  1
  •   Tisho star    12 年前

    看起来你真的很亲密。你从你的 encyrpted.EncodeBase64() 作用

    试试这个:

    string data = "H3uKbdyzrUo=";
    string b64str = Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(data));
    string clearText = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(b64str));
    
        3
  •  0
  •   Hector Correa Raj    12 年前

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

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

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

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

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