swift - 迅速。将字符串中的百分比编码符号转换为它们的 ascii 表示
问题描述
我正在使用 Swift 框架ASWebAuthenticationSession
通过浏览器为我的应用程序添加身份验证。处理凭据后,身份验证提供程序会发送带有特殊前缀的 URL,该 URL 会被我的应用程序拦截。URL 具有以下格式:
mycallback:un%3Dtest%26as%3D1%26token%3DeyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=
现在我想创建一个提取参数值的方法。所以我使用 URLComponents。我需要用'?'替换':',但是虽然它将百分比编码字符转换回ascii,但似乎无法正确解析url
(lldb) po URLComponents(string: "mycallback%3Fun%3Dtest%26as%3D1%26token%3DeyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=")
▿ Optional<URLComponents>
▿ some : mycallback%3Fun%3Dtest%26as%3D1%26token%3DeyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=
- path : "mycallback?un=test&as=1&token=eyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0="
(lldb) po URLComponents(string: "mycallback%3Fun%3Dtest%26as%3D1%26token%3DeyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=")?.queryItems
nil
另一种方法是按原样使用截获的 URL 并获取方案+路径,但我如何从这个结构中查询参数?
(lldb) po URLComponents(string: "mycallback:un%3Dtest%26as%3D1%26token%3DeyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=")
▿ Optional<URLComponents>
▿ some : mycallback:un%3Dtest%26as%3D1%26token%3DeyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=
- scheme : "mycallback"
- path : "un=test&as=1&token=eyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0="
仅当我提前手动将百分比 encodingp 符号转换为它们的 ascii 表示形式时,查询似乎还不错:
(lldb) po URLComponents(string: "mycallback?un=test&as=1&token=eyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=")
▿ Optional<URLComponents>
▿ some : mycallback?un=test&as=1&token=eyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=
- path : "mycallback"
▿ queryItems : 3 elements
▿ 0 : un=test
- name : "un"
▿ value : Optional<String>
- some : "test"
▿ 1 : as=1
- name : "as"
▿ value : Optional<String>
- some : "1"
▿ 2 : token=eyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=
- name : "token"
▿ value : Optional<String>
- some : "eyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0="
所以我的问题是如何将所有百分比编码符号(格式为 '%' 后跟十六进制值)转换为它们的 ascii 表示?
解决方案
您有一个方案所在的 URL,mycallback
路径实际上是一个查询。你只需要解析和调整它。
func decodedParameters(string: String) -> [URLQueryItem]? {
var c = URLComponents()
c.query = URLComponents(string: data)?.path
return c.queryItems
}
if let parameters = decodedParameters(string: data),
let token = parameters.first(where: { $0.name == "token"})?.value {
print(token)
}
// eyJiYmIiOiJBc2RhIiwgImRzY3ZnIjoiYXNhc2NkIn0=
如果你经常这样做,你可能更喜欢创建一个扩展来让它更容易一些:
extension Array where Element == URLQueryItem {
subscript(_ key: String) -> String? {
first(where: { $0.name == key})?.value
}
}
let parameters = decodedParameters(string: data) ?? []
if let token = parameters["token"] {
print(token)
}
推荐阅读
- python-3.x - Selenium/Python/Chrome:浏览器 Chrome 无法创建目录“Selenium”
- php - 内容类型标头的奇怪行为
- c++ - C ++确定数组的大小
- php - Google OAuth 屏幕:我需要验证吗?
- python - href类的python美丽汤问题
- android-studio - 检查您的模块类路径是否存在缺失或冲突的依赖项
- imagemagick - 将过滤后的图像输出到新文件夹并重命名它们
- javascript - 错误:找不到列:1054 未知列“p_categories.id”
- android - 在 onDraw() 和 onSizeChanged() 方法中,自定义视图的大小不是以像素为单位的。是否可以以像素为单位设置尺寸?
- c# - 使用光线投射防止破折号穿过墙壁