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 所需的步骤。
KeychainPayload
协议的 Payload。KeychainConfig
对象。Signer
和在步骤 2 中定义的 KeychainConfig
对象配置你的 Keychain
。Keychain
。现在详细查看每个步骤。
你的 payload 必须符合 KeychainPayload
协议,这意味着它必须包含:
init(expirationDate: Date, user: User) throws
func findUser(request: Request) -> EventLoopFuture<User>
,你可以在这里搜索在 init
方法中提供的用户。func verify(using signer: JWTSigner) throws
,它将验证你的 token 是否仍然有效。此外,你需要告诉你的 KeychainPayload
其 User
的 associatedtype
对应什么。
这是一个示例,它使用了 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
对象必须包含:
jwkIdentifier
expirationTimeInterval
并且你需要将你的 KeychainConfig
与你在步骤 1 中定义的 KeychainPayload
连接起来(KeychainConfig
为 KeychainPayload
定义了一个 typealias
)。
这是一个创建三个 KeychainConfig
对象的示例
UserAccessKeychainConfig
,标识符为 "access",expirationTimeInterval
为 300 秒UserRefreshKeychainConfig
,标识符为 "refresh",expirationTimeInterval
为 600 秒UserResetKeychainConfig
,标识符为 "reset",expirationTimeInterval
为 400 秒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
}
是时候将它们整合在一起了!在你的 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
了。你现在可以使用之前创建的 UserAccessKeychainConfig
、UserRefreshKeychainConfig
和 UserResetKeychainConfig
对象,通过调用 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 许可证开源的软件。