我有一个构建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;
}
非常感谢任何建议。
答案 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编码 - 两者都不区分大小写。
有关详细信息,请参阅以下链接
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正在从你发送的字符串中截断它。
这是完全的猜测,但我希望它有所帮助。