在 Swift 中解码 JSON Web 令牌
Posted
技术标签:
【中文标题】在 Swift 中解码 JSON Web 令牌【英文标题】:Decoding JSON Web Tokens in Swift 【发布时间】:2015-05-23 01:06:48 【问题描述】:尝试在 Swift 中解码 JWT 有效负载并且遇到了非常困难的时间
static func decodePayload(tokenstr: String)
//splitting JWT to extract payload
let arr = split(tokenstr) $0 == "."
//base64 encoded string i want to decode
let base64String = arr[1] as String
println(base64String) //eyJleHAiOjE0MjY4MjIxNjMsImlkIjoiNTUwYjA3NzM4ODk1NjAwZTk5MDAwMDAxIn0
//attempting to convert base64 string to nsdata
let nsdata: NSData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0))
//decoding fails because nsdata unwraps as nil
let base64Decoded: NSString = NSString(data: nsdata!, encoding: NSUTF8StringEncoding)!
【问题讨论】:
【参考方案1】:eyJleHAiOjE0MjY4MjIxNjMsImlkIjoiNTUwYjA3NzM4ODk1NjAwZTk5MDAwMDAxIn0
不是有效的 Base64 编码字符串,因为它的长度
不是 4 的倍数。一些 Base64 解码器可以容忍这个错误,但是
NSData
方法没有。
所以这实际上是服务器端创建的错误
Base64 编码的字符串。如有必要,您可以在您的应用程序中修复它
通过使用 =
字符添加所需的填充(针对 Swift 2 更新的代码):
var base64String = arr[1] as String
if base64String.characters.count % 4 != 0
let padlen = 4 - base64String.characters.count % 4
base64String += String(count: padlen, repeatedValue: Character("="))
现在解码按预期工作:
if let data = NSData(base64EncodedString: base64String, options: []),
let str = String(data: data, encoding: NSUTF8StringEncoding)
print(str) // "exp":1426822163,"id":"550b07738895600e99000001"
斯威夫特 4:
var base64String = "eyJleHAiOjE0MjY4MjIxNjMsImlkIjoiNTUwYjA3NzM4ODk1NjAwZTk5MDAwMDAxIn0"
if base64String.count % 4 != 0
let padlen = 4 - base64String.count % 4
base64String.append(contentsOf: repeatElement("=", count: padlen))
if let data = Data(base64Encoded: base64String) ,
let str = String(data: data, encoding: .utf8)
print(str) // "exp":1426822163,"id":"550b07738895600e99000001"
【讨论】:
最佳实践应该将 jwt 令牌存储在哪里?我一直在想它应该与用户名和密码一起存储到钥匙串中。 @user805981:我实际上对 jwt 令牌一无所知。但是,是的,密码等敏感数据应该存储在钥匙串中。 谢谢。关于钥匙扣。每个应用程序的钥匙串可以存储多少个钥匙串字典?每个应用程序是无限的还是一个密码钥匙串?【参考方案2】:以上解决方案对我有用,我已转换为 swift3
这里可以找到swift3代码
var base64Str = arr[1] as String
if base64Str.characters.count % 4 != 0
let padlen = 4 - base64Str.characters.count % 4
base64Str += String(repeating: "=", count: padlen)
if let data = Data(base64Encoded: base64Str, options: []),
let str = String(data: data, encoding: String.Encoding.utf8)
print(str)
【讨论】:
【参考方案3】:Swift 4 如下:
if let data = Data(base64Encoded: base64String, options: []),
let str = String(data: data as Data, encoding: String.Encoding.utf8)
print(str) // "exp":1426822163,"id":"550b07738895600e99000001"
【讨论】:
在 Swift 4 中,使用 Data 比使用 NSData 更好(使用 Data 比将 NSData 转换为 Data 更好)。 无论如何,@raju-abe 在他们的回答中已经给出了 Swift 3+ 的更新。请不要发布重复/不完整的内容。以上是关于在 Swift 中解码 JSON Web 令牌的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中解码 JWT(JSON Web 令牌)令牌?
解码 JSON Web 令牌 (Xamarin.Android)
如何解码我在 Swift 中收到 REST API 的 JWT 令牌?