SwiftJWT
Swift 的大头实现 JSON Web Token (JWT)。JWT 提供了轻便和紧凑的信息传输格式,可以在各方之间传输信息,并且由于 JWT 是数字签名的,因此信息可以被验证和信任。
有关 JSON Web Token 的更多信息,包括其用例和如何工作,我们建议您访问 jwt.io。
注意:作为 JWS 发送的 JWT 不 对数据进行加密,因此绝不要发送任何敏感或机密信息在 JWT 中。此库目前不支持 JWE。
Swift 版本
Swift-JWT 最新版本需要 Swift 4.0 或更高版本。您可以点击这个 链接 下载 Swift 二进制文件。与其他 Swift 版本的兼容性无法保证。
用法
Swift 包管理器
添加依赖项
将 Swift-JWT
包添加到你的应用程序 Package.swift
文件中的依赖项中。将 "x.x.x"
替换为最新的 Swift-JWT
版本。
.package(url: "https://github.com/IBM-Swift/Swift-JWT.git", from: "x.x.x")
将 SwiftJWT
添加到你的目标的依赖项
.target(name: "example", dependencies: ["SwiftJWT"]),
导入包
import SwiftJWT
CocoaPods
要在使用 CocoaPods 的项目中包含 Swift-JWT
,请将 SwiftJWT
添加到你的 Podfile 中
pod 'SwiftJWT'
开始使用
JWT 模型
在其压缩形式中,JSON Web Tokens 由三个用点(.)分隔的 Base64Url 编码 JSON 部分组成。
这些部分是:头部(Headers)、声明(Claims)和签名(Signature)。因此,JWT 通常如下所示:xxxxx.yyyyy.zzzzz
头部
Header
结构体包含由 RFC7515 定义的自定义 JSON Web Token 的头部字段。
"typ" 头部默认为 "JWT"。当您对 JWT 进行签名时,“alg” 头部将设置为算法名称。
其他头部字段可以在初始化 Header
结构体时设置,也可以通过直接修改头部对象来更改。
let myHeader = Header(kid: "KeyID1")
声明
声明是关于实体(通常是用户)的陈述以及附加数据。声明通过创建一个符合 Claims
协议的 Swift 类型来定义。此类型的字段代表将使用 JWT 共享的信息。
推荐声明列表已在 RFC7519 中定义。
struct MyClaims: Claims {
let iss: String
let sub: String
let exp: Date
let admin: Bool
}
let myClaims = MyClaims(iss: "Kitura", sub: "John", exp: Date(timeIntervalSinceNow: 3600), admin: true)
ClaimsExamples
本库包括一些按其在线规范定义的 Claims
结构体示例。
JWT
JWT
结构体代表一个 JSON Web Token 的 Header
和 Claims
。
您可以通过解码 JWT 字符串或提供 JWT 头部和声明来初始化 JWT。
let myJWT = JWT(header: myHeader, claims: myClaims)
签名和验证 JSON Web token
创建公钥和私钥
要使用 RSA 算法签名并验证 JWT,您必须提供公钥和私钥。这可以是以下终端命令生成的 .key 文件内容:
$ ssh-keygen -t rsa -b 4096 -m PEM -f privateKey.key
# Don't add a passphrase
$ openssl rsa -in privateKey.key -pubout -outform PEM -out privateKey.key.pub
这将在您的系统上创建一对公钥和私钥,并且可以使用以下代码将私钥内容传递给 Swift 变量:
let privateKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/privateKey.key"))
let privateKey: Data = try Data(contentsOf: privateKeyPath, options: .alwaysMapped)
let publicKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/publicKey.key"))
let publicKey: Data = try Data(contentsOf: publicKeyPath, options: .alwaysMapped)
有关创建椭圆曲线公钥和私钥的详细信息,请参阅 BlueECC README.txt。
使用 JWTSigner 签名 JWT
JWTSigner 结构体包含了可以用来签名 JWT 的算法。
使用与所需 RSA 算法对应的静态函数初始化 JWTSigner。
let jwtSigner = JWTSigner.rs256(privateKey: privateKey)
要生成已签名的 JWT 字符串,请在 JWT 实例上调用 sign
函数,并传入 JWTSigner。
let signedJWT = try myJWT.sign(using: jwtSigner)
生成的 signedJWT
将是以下形式的 String
:
<encoded header>.<encoded claims>.<signature>
注意:签名函数设置了头部的 alg (算法) 字段。
使用 JWTVerifier 验证 JWT
JWTVerifier 结构体包含了可以用来验证 JWT 的算法。
使用与所需 RSA 算法对应的静态函数初始化 JWTVerifier。
let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)
要验证已签名的 JWT 字符串,请调用静态 verify
函数,传入 JWT 字符串和 JWTVerifier。
let verified = JWT<MyClaims>.verify(signedJWT, using: jwtVerifier)
如果签名验证成功,verified
字段将是 bool
类型的值为真。
受支持算法
用于签名和验证 JWT 的受支持算法如下:
- RS256 - 使用 SHA-256 的 RSASSA-PKCS1-v1_5
- RS384 - 使用 SHA-384 的 RSASSA-PKCS1-v1_5
- RS512 - 使用 SHA-512 的 RSASSA-PKCS1-v1_5
- HS256 - 使用 SHA-256 的 HMAC
- HS384 - 使用 SHA-384 的 HMAC
- HS512 - 使用SHA-512进行HMAC
- ES256 - 使用SHA-256和P-256曲线进行ECDSA
- ES384 - 使用SHA-384和P-384曲线进行ECDSA
- ES512 - 使用SHA-512和P-521曲线进行ECDSA
- PS256 - 使用SHA-256进行RSA-PSS
- PS384 - 使用SHA-384进行RSA-PSS
- PS512 - 使用SHA-512进行RSA-PSS
- none - 不对JWT进行签名或验证
注意:ECDSA和RSA-PSS算法需要Swift 4.1及更高版本。
验证声明
validateClaims
函数验证JWT实例的标准Date
声明。如果Claims
对象中存在以下声明,则会验证
- exp(过期日期)
- nbf(开始日期)
- iat(发行日期)
此方法返回ValidateClaimsResult
- 一个结构体,列出了各种验证失败的 reasons。如果验证成功,则返回ValidateClaimsResult.success
。leeway
参数是秒数,表示标准Date
声明超出指定时间外的有效时间。这可以用来弥补发行者和验证者之间的时钟偏差。
let validationResult = verified.validateClaims(leeway: 10)
if validationResult != .success {
print("Claims validation failed: ", validationResult)
}
从JWT字符串解码JWT
可以从JWT字符串初始化JWT结构体。如果提供了JWTVerifier,它将在初始化之前验证签名
let newJWT = try JWT<MyClaims>(jwtString: signedJWT, verifier: jwtVerifier)
JWTEncoder和JWTDecoder
JWTEncoder和JWTDecoder类使用与JSONEncoder和JSONDecoder相同的API进行JWT字符串的编解码
let jwtEncoder = JWTEncoder(jwtSigner: jwtSigner)
let jwtString = try jwtEncoder.encodeToString(myJWT)
let jwtDecoder = JWTDecoder(jwtVerifier: jwtVerifier)
let jwt = try jwtDecoder.decode(JWT<MyClaims>.self, fromString: jwtString)
因为JWTEncoder和JWTDecoder遵循KituraContract的 BodyEncoder和BodyDecoder协议,所以它们可以用作自定义编解码器,用于在可编码路由中发送和接收JWT
router.encoders[MediaType(type: .application, subType: "jwt")] = { return jwtEncoder }
router.decoders[MediaType(type: .application, subType: "jwt")] = { return jwtDecoder }
这允许使用JWT进行信息交换。通过发送和接收JWT,您可以确保发送者是其所称的人,并验证内容没有被篡改。
API 文档
更多信息请访问我们的 API 参考。
社区
我们热衷于讨论服务器端 Swift 和 Kitura。加入我们的 Slack,与团队见面!
许可证
本库采用 Apache 2.0 许可。完整许可证文本可在 LICENSE 中找到。