如何使用 Alamofire 的 RequestAdapter 将 firebase ID 令牌设置为全局标头?

Posted

技术标签:

【中文标题】如何使用 Alamofire 的 RequestAdapter 将 firebase ID 令牌设置为全局标头?【英文标题】:How do I use Alamofire's RequestAdapter to set firebase ID token as a global header? 【发布时间】:2020-07-27 20:19:30 【问题描述】:

使用 firebase 对用户进行身份验证后,我将获得 ID 令牌,因为我的 REST 服务正在使用 firebase 令牌进行身份验证。

ios 方面,我想存储这个令牌,以便我发出的每个请求都将使用令牌设置 Authorization 标头。

Alamofire 文档建议使用 RequestAdapter https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#requestadapter

所以我做了一个 TokenInterceptor:

import Foundation
import Alamofire

final class TokenInterceptor: Alamofire.RequestInterceptor 
    private var token: String
    
    init(token: String) 
        self.token = token
    
    
    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) 
        var urlRequest = urlRequest

        urlRequest.setValue("Bearer " + self.token, forHTTPHeaderField: "Authorization")

        completion(.success(urlRequest))
    

然后我想使用它,但我不明白如何将它与AFSession 一起使用。这是我的状态类:

import Foundation
import FirebaseAuth
import Alamofire

class AuthenticationState: NSObject, ObservableObject 
    @Published var user: User?
    @Published var error: NSError?
    @Published var loading: Bool = true
    
    private let auth = Auth.auth()
    
    private var fbUser: FirebaseAuth.User?
    
    func signInWithEmailPassword(email: String, password: String) 
        self.auth.signIn(withEmail: email, password: password, completion: handleAuthResultCompletion)
    
    
    private func handleAuthResultCompletion(auth: AuthDataResult?, error: Error?) 
        DispatchQueue.main.async 
            self.loading = false
            if let fbUser = auth?.user 
                self.fbUser = fbUser
                fbUser.getIDTokenForcingRefresh(true)  idToken, error in
                  if let error = error 
                    // Handle error
                  
                
                    // What am I to do here?  How does this affect AF namespace? 
                    Session(interceptor: RequestInterceptor(token: idToken ?? ""))
                    
                    self.me()
                
             else if let error = error 
                self.error = error as NSError
            
        
    
    
    private func me() 
        AF.request("http://localhost:8080/api/v1/me").response  response in
            print(response)
        
    

【问题讨论】:

【参考方案1】:

您可以在每个Session 或每个Request 的基础上使用RequestAdapterSession 的初始化器可以取值,然后用于所有请求:

let session = Session(interceptor: Interceptor(adapter: YourAdapter()))

或者您可以根据请求进行设置:

AF.request(..., interceptor: Interceptor(adapter: YourAdapter()).response ...

您可以在我们的Session documentation 或Request documentation 阅读更多内容。

【讨论】:

谢谢乔恩。我听从了您的建议,并将这个自定义会话设置为我上面的 AuthenticationState 类的私有变量。然后我添加了一个authenticatedRequest(),我可以将URL Convertible 参数传递给它,它将使用私人会话。由于我将它用作环境对象,因此我的任何视图都可以使用 authenticatedRequest。当您说建议使用此自定义会话时,这就是您的意思吗?谢谢,我还在学习,所以如果我说错了任何术语,请告诉我。 我不建议将 Sessions 单独用于未经身份验证和经过身份验证的呼叫。相反,您可以使用 per-Request API 仅将适配器附加到需要进行身份验证的请求。这里有很多方法,包括您的便捷方法,或者使用我们的URLRequestConvertible 协议为请求构建所有内容。 谢谢!这是有道理的

以上是关于如何使用 Alamofire 的 RequestAdapter 将 firebase ID 令牌设置为全局标头?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Alamofire 为 http 请求编写单元测试?

如何使用操作查询发出多个 Alamofire 请求

如何使用 alamofire 实现 put http 请求

如何使用 Alamofire 更改全局变量?

如何使用 AlamoFire 下载 blob URI

如何使用 Swift 3 将单例与 Alamofire 一起使用?