OpenAPI Generator Swift 5 客户端如何实现 Bearer Token 认证?
发布时间:2026/9/13 17:03:37来源:尧图网络
OpenAPI Generator Swift 5 客户端如何实现 Bearer Token 认证【免费下载链接】openapi-generatorOpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)项目地址: https://gitcode.com/GitHub_Trending/op/openapi-generator用 OpenAPI Generator 的swift5生成器产出的 Swift 客户端默认只负责按 OpenAPI 3.0 文档生成 API 调用代码不会替你处理 Bearer Token 的注入与刷新请求发出时没有Authorization头收到 401 也不会自动换 token 重试。本文解决的问题就是在swift5生成的客户端默认 URLSession HTTP 库里让每个需要认证的请求自动带上Authorization: Bearer token头并在服务端返回 401 时刷新 token 后自动重试。前提与适用条件客户端由swift5生成器生成-g swift5HTTP 库为默认的urlsessionalamofire库的写法见后文可选分支OpenAPI 文档中使用了httpbearerOpenAPI 3.0 的BearerToken安全方案。swift5的 Security Feature 表中BearerToken标记为支持、仅适用于 OAS3见 docs/generators/swift5.md生成的 API 类名以项目名projectName为基础下文的PetstoreClientAPI在换成你自己的projectName后会相应变化这一点官方文档明确提示The namePetstoreClientAPI.requestBuilderFactorywill change depending on your project name。先说明一个状态docs/generators/swift5.md 的 METADATA 中将swift5生成器标记为DEPRECATED官方建议新项目改用swift6其认证走OpenAPIClient.shared.interceptor拦截器机制机制完全不同。如果你正在新建客户端见文末限制与迁移提示。实现思路自定义 RequestBuilderFactoryswift5客户端把所有 HTTP 请求的构造和发送都委托给RequestBuilderFactory提供的RequestBuilder类。因此 Bearer 认证不需要改动生成代码只需四件套BearerRequestBuilderFactoryRequestBuilderFactory子类返回下面两个自定义 BuilderBearerRequestBuilder/BearerDecodableRequestBuilder分别继承URLSessionRequestBuilderT和URLSessionDecodableRequestBuilderT重写execute在发请求前注入 token并处理 401 重试BearerTokenHandlertoken 的存取与刷新策略何时换新 token、何时判定为 401装配把工厂赋给生成 API 类的requestBuilderFactory属性。仓库里的可运行样例位于 samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerDecodableRequestBuilder.swift 和 samples/client/petstore/swift5/urlsessionLibrary/SwaggerClientTests/SwaggerClient/AppDelegate.swift以下代码取自该样例即 docs/faq-generators.md 中 How do I implement bearer token authentication with URLSession on the Swift 5 API client? 一节指向的实现。第一步实现 BearerTokenHandlertoken 存取与 401 判断class BearerTokenHandler { private static var bearerToken: String? nil static func refreshTokenIfDoesntExist(completionHandler: escaping (String) - Void) { if let bearerToken bearerToken { completionHandler(bearerToken) } else { startRefreshingToken { token in completionHandler(token) } } } static func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse?, error: Error?, completionHandler: escaping (Bool, String?) - Void) { if let response response as? HTTPURLResponse, response.statusCode 401 { startRefreshingToken { token in completionHandler(true, token) } } else { completionHandler(false, nil) } } private static func startRefreshingToken(completionHandler: escaping (String) - Void) { // Get a bearer token —— 样例中此处是占位需要替换为你自己的取 token 逻辑 let dummyBearerToken ... bearerToken dummyBearerToken completionHandler(dummyBearerToken) } }这个类是整个方案里唯一需要你真正替换样例占位值的地方startRefreshingToken里的dummyBearerToken ...只是样例写法改成你的真实取 token 流程向认证服务换取 token 等。refreshTokenIfDoesntExist在每次发请求前被调用内存里有 token 就直接回调没有就先刷新refreshTokenIfUnauthorizedRequestResponse只在响应状态码为 401 时返回wasTokenRefreshed true并带出新 token其余情况返回false——这就是重试与否的全部判定依据。token 只保存在内存静态变量中文档未提供持久化或 keychain 写法。第二步子类化 Request Builder注入 Authorization 头可解码请求有具体返回模型用BearerDecodableRequestBuilder样例完整实现class BearerDecodableRequestBuilderT: Decodable: URLSessionDecodableRequestBuilderT { discardableResult override func execute(_ apiResponseQueue: DispatchQueue PetstoreClientAPI.apiResponseQueue, _ completion: escaping (ResultResponseT, ErrorResponse) - Void) - RequestTask { guard self.requiresAuthentication else { return super.execute(apiResponseQueue, completion) } // Before making the request, we can validate if we have a bearer token to be able to make a request BearerTokenHandler.refreshTokenIfDoesntExist { token in self.addHeaders([Authorization: Bearer \(token)]) // Here we make the request super.execute(apiResponseQueue) { result in switch result { case .success: // If we got a successful response, we send the response to the completion block completion(result) case let .failure(error): // If the error is an ErrorResponse.error() we will analyse it to see if its a 401, and if its a 401, we will refresh the token and retry the request if case let ErrorResponse.error(_, data, response, error) error { BearerTokenHandler.refreshTokenIfUnauthorizedRequestResponse( data: data, response: response, error: error ) { (wasTokenRefreshed, newToken) in if wasTokenRefreshed, let newToken newToken { // If the token was refreshed, its because it was a 401 error, so we refreshed the token, and we are going to retry the request by calling self.execute() self.addHeaders([Authorization: Bearer \(newToken)]) self.execute(apiResponseQueue, completion) } else { // If the token was not refreshed, its because it was not a 401 error, so we send the response to the completion block completion(result) } } } else { // If its an unknown error, we send the response to the completion block completion(result) } } } } return requestTask } }执行路径逐条对应guard self.requiresAuthentication不成立该操作在 OpenAPI 文档中没有声明安全方案时直接走父类原逻辑不注入任何认证头需要认证时先经refreshTokenIfDoesntExist确保有 token再通过self.addHeaders([Authorization: Bearer \(token)])把头挂到本次请求上请求失败且属于ErrorResponse.error时交给BearerTokenHandler判定是 401 就刷新 token、更新头并调用self.execute(apiResponseQueue, completion)重发不是 401 就把失败结果原样交给 completion。非解码请求无具体返回模型对应BearerRequestBuilderT: URLSessionRequestBuilderT逻辑与上面完全相同只是继承的父类和apiResponseQueue默认参数一致。两个类都在样例文件 BearerDecodableRequestBuilder.swift 中可直接对照复制。第三步工厂类并装配到生成的 API 上class BearerRequestBuilderFactory: RequestBuilderFactory { func getNonDecodableBuilderT() - RequestBuilderT.Type { BearerRequestBuilderT.self } func getBuilderT: Decodable() - RequestBuilderT.Type { BearerDecodableRequestBuilderT.self } }装配只需一行放在应用启动处iOS 示例即AppDelegate的didFinishLaunchingWithOptions样例见 AppDelegate.swiftPetstoreClientAPI.requestBuilderFactory BearerRequestBuilderFactory()PetstoreClientAPI是样例的项目名产物换成你projectName对应的你的ProjectNameAPI。FAQ 与样例代码在细节上略有出入FAQ 一节的startRefreshingToken还会写PetstoreClientAPI.customHeaders[Authorization]全局头而仓库样例改为在每次execute中通过addHeaders注入。本文以仓库样例为准两种写法都出自官方文档。结果如何验证文档没有给出单独的验证命令行为判断依据就是上面代码的实际路径调用受安全方案保护的接口后成功响应落入case .success说明带 token 的请求已被服务端接受completion 收到Result.success服务端返回 401 时refreshTokenIfUnauthorizedRequestResponse返回wasTokenRefreshed true请求会自动用新 token 重发一次重发仍失败则失败结果交给你的 completion 处理非 401 的错误不触发刷新直接透传避免无限重试。也就是说换 token 后自动重试是否生效可以在你的真实 token 服务上观察一次过期 token 请求 → 401 → 重发来确认。可选分支Alamofire HTTP 库如果生成时用--additional-propertieslibraryalamofireswift5支持的库为urlsession默认、alamofire、vapor见 docs/generators/swift5.md 的library选项写法改为子类化AlamofireRequestBuilder/AlamofireDecodableRequestBuilder重写createSessionManager()把同一个BearerTokenHandler此时需实现 Alamofire 的RequestAdapter、RequestRetrier协议挂到sessionManager.adapter和sessionManager.retrier上同样最后执行PetstoreClientAPI.requestBuilderFactory BearerRequestBuilderFactory()。要点摘录自 docs/faq-generators.md 的 Alamofire 小节class BearerRequestBuilderT: AlamofireRequestBuilderT { override func createSessionManager() - SessionManager { let sessionManager super.createSessionManager() let bearerTokenHandler BearerTokenHandler() sessionManager.adapter bearerTokenHandler sessionManager.retrier bearerTokenHandler return sessionManager } }func adapt(_ urlRequest: URLRequest) throws - URLRequest { if let bearerToken Self.bearerToken { var urlRequest urlRequest urlRequest.setValue(Bearer \(bearerToken), forHTTPHeaderField: Authorization) return urlRequest } return urlRequest } func should(_: SessionManager, retry request: Request, with _: Error, completion: escaping RequestRetryCompletion) { if let response request.task?.response as? HTTPURLResponse, response.statusCode 401 { Self.startRefreshingToken { isTokenRefreshed in completion(isTokenRefreshed, 0.0) } } else { completion(false, 0.0) } }完整实现见 docs/faq-generators.md 对应小节及samples/client/petstore/swift5/alamofireLibrary目录下的样例。限制与迁移提示本文方案仅适用于swift5生成器该生成器在 docs/generators/swift5.md 中已标记 DEPRECATED。迁移到swift6时认证机制不同实现OpenAPIInterceptor协议intercept中requestBuilder.requiresAuthentication判断后设置Authorization头retry中处理 401 刷新再执行OpenAPIClient.shared.interceptor BearerOpenAPIInterceptor()写法见 docs/faq-generators.md 的 Swift 6 小节Bearer Token 支持对应 OpenAPI 3.0 的BearerToken安全方案BasicAuth、ApiKey、各 OAuth2 流程同样受支持OpenIDConnect、SignatureAuth不支持见同一文档的 Security Feature 表文档给出的 token 获取均为占位实现真实的换取、存储与有效期策略需要你按自己的认证服务实现文档不提供这部分。【免费下载链接】openapi-generatorOpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)项目地址: https://gitcode.com/GitHub_Trending/op/openapi-generator创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网