我想将一些 URL 编码数据从 Swift 应用程序发送到 PHP API,在其中数据再次被解码。
虽然这在大多数情况下工作得很好,但我现在意识到 PHP urldecode 处理 + 号的方式与 Swift movingPercentEncoding 不同,并将 + 解码为空格。
如何避免这种情况?
// Swift
let data = "some+test"
let encodedData = data.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) // some+test
sendToMyServer(encodedData)
// PHP
$encodedData = $receivedData; // some+text
$decodedData = urldecode($encodedData); // some text
看来 Swift 不考虑其任何内置(倒置)字符集中的 + 号:
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}
URLHostAllowedCharacterSet "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet "#%<>[\]^`{|}
URLUserAllowedCharacterSet "#%/:<>?@[\]^`
PHP 以这种方式处理+号有什么原因吗?
解决这个问题的“正确”方法是什么?我假设我可以简单地定义一个包含+号的自定义字符集,但我不确定这是否会导致其他意外的副作用。这安全吗?PHP urldecode 是否还有其他需要考虑的差异?
原因:
CharacterSet.urlHostAllowed
的文档:
返回主机 URL 子组件中允许的字符集。
URLComponents
的隐式链接文档
此结构根据 RFC 3986 解析和构造 URL。其行为与符合旧 RFC 的 URL 结构的行为略有不同。但是,您可以根据 URLComponents 值的内容轻松获取 URL 值,反之亦然。
urldecode
说:
加号 ('+') 被解码为空格字符。
urlencode
说:
这与 » RFC 3986 编码(请参阅 rawurlencode())不同,因为由于历史原因,空格被编码为加号 (+)。
所以 iOS 使用
RFC 3986
而 PhP 则没有。
解决方案:
通过在 iOS 或服务器上更改它来使用相同的编码/解码。
对于服务器更改:
rawurldecode
(或 rawurlencode
,如果需要),如下所示:
rawurldecode() 不会将加号 ('+') 解码为空格。 urldecode() 可以。
和
rawurlencode — 根据 RFC 3986 进行 URL 编码
对于 iOS 更改:
参见 Sajjad 的回答