6

[这可能不完全是一个编程问题,但它是一个程序员可能最好回答的难题。我首先在 Pro Webmasters 网站上进行了尝试,结果一片寂静]

我们的网站上有一个电子邮件地址验证流程。该站点首先生成一个适当的密钥作为字符串

mykey

然后它将该密钥编码为一堆字节

&$dac~ʌ����!

然后它 base64 编码那一堆字节

JiRkYWN+yoyIhIQ==

由于此键将作为要放置在 HTML 电子邮件中的 URL 的查询字符串值给出,因此我们需要先对其进行 URLEncode,然后对结果进行 HTMLEncode,给我们(在示例情况下 HTMLEncoding 没有效果,但是我不会费心去修改这个例子)

JiRkYWN%2ByoyIhIQ%3D%3D

然后将其嵌入到作为电子邮件的一部分发送的 HTML 中,例如:

click <a href="http://myapp/verify?key=JiRkYWN%2ByoyIhIQ%3D%3D">here</a>. 
Or paste <b>http://myapp/verify?key=JiRkYWN%2ByoyIhIQ%3D%3D</b> into your browser.

当接收用户点击链接时,站点接收请求,提取查询字符串“key”参数的值,base64 对其进行解码、解密,并根据站点逻辑执行适当的操作。

但是,有时我们有用户报告他们的点击无效。一位这样的用户向我们转发了他发送的电子邮件,并且在检查时 HTML 已被转换为(按照上面的示例)

click <a href="http://myapp/verify?key=JiRkYWN+yoyIhIQ%3D%3D">here</a>
Or paste <b>http://myapp/verify?key=JiRkYWN+yoyIhIQ%3D%3D</b> into your browser.

也就是说,%2B 字符串 - 但没有其他百分比编码的字符串 - 已转换为加号。(它肯定给我们留下了正确的值——我已经查看了适当的 SMTP 日志)。

key=JiRkYWN%2ByoyIhIQ%3D%3D
key=JiRkYWN+yoyIhIQ%3D%3D

所以我认为有两种可能:

  1. 我正在做的事情很愚蠢,我看不到,或者

  2. 一些邮件客户端将 %2b 字符串转换为加号,也许是为了解决人们错误地 URLEncoding 加号的问题

如果是 1 - 它是什么?如果是 2 - 是否有一种标准的、已知的处理这种情况的方法?

非常感谢您的帮助

4

2 回答 2

1

问题出在这一步

经检查,HTML 已被转换为(根据上面的示例)

click <a href="http://myapp/verify?key=JiRkYWN+yoyIhIQ%3D%3D">here</a>
Or paste <b>http://myapp/verify?key=JiRkYWN+yoyIhIQ%3D%3D</b> into
your browser.

也就是说,%2B 字符串 - 但没有其他百分比编码字符串 - 已转换为加号

您在“另一端”的应用程序必须缺少取消转义的步骤。无论是否存在 %2B 或 + 之类的函数, perls uri_unescape 都会返回一致的答案

DB<9> use URI::Escape;
DB<10> x uri_unescape("JiRkYWN+yoyIhIQ%3D%3D")
0  'JiRkYWN+yoyIhIQ=='
DB<11> x uri_unescape("JiRkYWN%2ByoyIhIQ%3D%3D")
0  'JiRkYWN+yoyIhIQ=='

这是应该发生的事情。我展示的只是步骤。我在调试器中使用 perl。步骤 54 将字符串编码为 base64。步骤 55 显示了如何将 base64 编码的字符串变成 uri 转义参数。步骤 56 和 57 是客户端应该做的解码。

一种可能的解决方法是确保您的 base64“密钥”不包含任何加号!

  DB<53> $key="AB~"
  DB<54> x encode_base64($key)
0  'QUJ+
'
  DB<55> x uri_escape('QUJ+') 
0  'QUJ%2B'
  DB<56> x uri_unescape('QUJ%2B')
0  'QUJ+'
  DB<57> $result=decode_base64('QUJ+')
  DB<58> x $result
0  'AB~'
于 2013-09-06T09:52:42.813 回答
1

这里可能发生的是 URLDecode 正在将%2b转换为+,它被解释为 URL 中的空格字符。我能够通过首先对字符串进行url解码,然后使用替换函数将解码字符串中的空格替换为+字符,然后解密“固定”字符串来克服类似的问题。

于 2016-12-28T23:33:30.557 回答