Keychain ⛓

Swift Version Vapor Version tests Readme Score GitHub license

Keychain 为你的 API 项目添加了一个完整且可定制的用户身份验证系统。

📦 安装

更新你的 Package.swift 文件。

.package(url: "https://github.com/nodes-vapor/keychain.git", from: "2.0.0")
targets: [
    .target(
        name: "App",
        dependencies: [
            ...
            .product(name: "Keychain", package: "keychain"),
        ]
    ),
    ...
]

用法

以下是在你的项目中使用 Keychain 所需的步骤。

  1. 定义一个符合 KeychainPayload 协议的 Payload。
  2. 为你想要使用的密钥类型创建 KeychainConfig 对象。
  3. 使用 Signer 和在步骤 2 中定义的 KeychainConfig 对象配置你的 Keychain
  4. 真正开始使用你的 Keychain

现在详细查看每个步骤。

定义 Payload

你的 payload 必须符合 KeychainPayload 协议,这意味着它必须包含:

此外,你需要告诉你的 KeychainPayloadUserassociatedtype 对应什么。

这是一个示例,它使用了 JWT token 中的元素,并验证了过期时间 (exp) claim 是否已过期。请注意,在本例中 findUser 仅返回一个测试用户。在实际应用中,你可能需要在存储用户的位置进行查找。

import JWT
import Keychain
import Vapor

struct UserJWTPayload: KeychainPayload {
    let exp: ExpirationClaim
    let sub: SubjectClaim

    init(expirationDate: Date, user: User) {
        self.exp = .init(value: expirationDate)
        self.sub = .init(value: user.id)
    }

    func findUser(request: Request) -> EventLoopFuture<User> {
        request.eventLoop.future(request.testUser).unwrap(or: TestError.userNotFound)
    }

    func verify(using signer: JWTSigner) throws {
        try exp.verifyNotExpired()
    }
}

创建 KeychainConfig 对象

你的 KeychainConfig 对象必须包含:

并且你需要将你的 KeychainConfig 与你在步骤 1 中定义的 KeychainPayload 连接起来(KeychainConfigKeychainPayload 定义了一个 typealias)。

这是一个创建三个 KeychainConfig 对象的示例

import JWT
import Keychain

struct UserAccessKeychainConfig: KeychainConfig, Equatable {
    typealias JWTPayload = UserJWTPayload

    static var jwkIdentifier: JWKIdentifier = "access"

    let expirationTimeInterval: TimeInterval = 300
}

struct UserRefreshKeychainConfig: KeychainConfig, Equatable {
    typealias JWTPayload = UserJWTPayload

    static var jwkIdentifier: JWKIdentifier = "refresh"

    let expirationTimeInterval: TimeInterval = 600
}

struct UserResetKeychainConfig: KeychainConfig, Equatable {
    typealias JWTPayload = UserJWTPayload

    static var jwkIdentifier: JWKIdentifier = "reset"

    let expirationTimeInterval: TimeInterval = 400
}

配置你的 Keychain

是时候将它们整合在一起了!在你的 configure.swift 文件中,你可以添加多个 KeychainConfig 对象,如下所示

app.keychain.configure(
    signer: .hs256(key: YourKeyGoesHere...ProbablyReadFromSomeEnvironment),
    config: UserAccessKeychainConfig()
)
app.keychain.configure(
    signer: JWTSigner(
        algorithm: TestJWTAlgorithm(name: UserRefreshKeychainConfig.jwkIdentifier.string)
    ),
    config: UserRefreshKeychainConfig()
)
app.keychain.configure(
    signer: JWTSigner(
        algorithm: TestJWTAlgorithm(name: UserResetKeychainConfig.jwkIdentifier.string)
    ),
    config: UserResetKeychainConfig()
)

请注意 signer 参数。你可以使用内置的 signer 之一,如第一个示例,我们使用了带有密钥的 .hs256 signer。或者,你可以提供你自己的 signer,如最后两个示例所示。

真正开始使用你的 Keychain

完成所有设置后,是时候放松一下并充分利用 Keychain 了。你现在可以使用之前创建的 UserAccessKeychainConfigUserRefreshKeychainConfigUserResetKeychainConfig 对象,通过调用 makeToken(on:, currentDate:) 来生成 JWT tokens。

这是一个关于如何生成新的 refreshToken 的示例。

import Keychain

struct UserController {
    let currentDate: () -> Date

    ...

    func refreshToken(request: Request) throws -> Response {
        let token = try UserRefreshKeychainConfig.makeToken(on: request, currentDate: currentDate())

        // here we encode the token string as JSON but you might include your token in a struct
        // conforming to `Content`
        let response = Response()
        try response.content.encode(token, as: .json)
        return response
    }
}

🏆 鸣谢

此软件包由 Monstarlab 的 Vapor 团队开发和维护。

📄 许可证

此软件包是根据 MIT 许可证开源的软件。