Kitura

SwiftJWT

使用 Swift 实现的 JSON Web Token。JWT 提供了一种轻量且紧凑的格式,用于在各方之间传输信息。由于 JWT 经过数字签名,因此可以验证和信任该信息。

有关 JSON Web Token 的更多信息、其用例以及工作原理,我们建议访问 jwt.io

提醒: 作为 JWS 发送的 JWT 加密数据,因此切勿在 JWT 中发送任何敏感或机密信息。此库目前不支持 JWE。

Swift 版本

最新版本的 Swift-JWT 需要 Swift 5.2 或更高版本。您可以通过此链接下载此版本的 Swift 二进制文件。不保证与其他 Swift 版本的兼容性。

用法

Swift Package Manager

添加依赖项

Swift-JWT 包添加到应用程序的 Package.swift 文件中的依赖项中。将 "x.x.x" 替换为最新的 Swift-JWT release

.package(url: "https://github.com/Kitura/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 Token 由三个部分组成,这些部分是 Base64Url 编码的 JSON,以点 (.) 分隔。
这些部分是:标头、声明和签名。因此,JWT 通常如下所示:xxxxx.yyyyy.zzzzz

标头

Header 结构包含 RFC7515 定义的 JSON Web Token 标头的字段。
"typ" 标头将默认为 "JWT"。当您签署 JWT 时,"alg" 标头将设置为算法名称。
其他标头字段可以在初始化标头时设置,也可以直接在标头对象上更改它们。

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)
声明示例

此库包含一些示例 Claims 结构,这些结构根据其在线规范定义。

JWT

JWT 结构表示 JSON Web Token 的 HeaderClaims
您可以通过解码 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>

注意: sign 函数设置标头的 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,值为 true。

支持的算法

支持的用于签名和验证 JWT 的算法有

注意:ECDSA 和 RSA-PSS 算法需要最低 Swift 版本 4.1。

验证声明

validateClaims 函数验证 JWT 实例的标准 Date 声明。如果以下声明存在于 Claims 对象中,则将对其进行验证

该方法返回 ValidateClaimsResult - 一个结构体,列出了验证失败的各种原因。如果验证成功,则返回 ValidateClaimsResult.successleeway 参数是以秒为单位的 TimeInterval,标准 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's BodyEncoder 和 BodyDecoder 协议,因此它们可以用作 自定义编码器,在 Codable 路由中发送和接收 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 中获得。