Tôi đã có thể thực hiện triển khai ví dụ OAuth đang hoạt động như được cung cấp bởi AlamoFire. Tuy nhiên, tôi đang tìm hiểu một số dòng mã và cách thức hoạt động của nó.Hiểu ví dụ về AlamoFire OAuth
Full Ví dụ:
class OAuth2Handler: RequestAdapter, RequestRetrier {
private typealias RefreshCompletion = (_ succeeded: Bool, _ accessToken: String?, _ refreshToken: String?) -> Void
private let sessionManager: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
private let lock = NSLock()
private var clientID: String
private var baseURLString: String
private var accessToken: String
private var refreshToken: String
private var isRefreshing = false
private var requestsToRetry: [RequestRetryCompletion] = []
// MARK: - Initialization
public init(clientID: String, baseURLString: String, accessToken: String, refreshToken: String) {
self.clientID = clientID
self.baseURLString = baseURLString
self.accessToken = accessToken
self.refreshToken = refreshToken
}
// MARK: - RequestAdapter
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
if let urlString = urlRequest.url?.absoluteString, urlString.hasPrefix(baseURLString) {
var urlRequest = urlRequest
urlRequest.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
return urlRequest
}
return urlRequest
}
// MARK: - RequestRetrier
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
lock.lock() ; defer { lock.unlock() }
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
requestsToRetry.append(completion)
if !isRefreshing {
refreshTokens { [weak self] succeeded, accessToken, refreshToken in
guard let strongSelf = self else { return }
strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }
if let accessToken = accessToken, let refreshToken = refreshToken {
strongSelf.accessToken = accessToken
strongSelf.refreshToken = refreshToken
}
strongSelf.requestsToRetry.forEach { $0(succeeded, 0.0) }
strongSelf.requestsToRetry.removeAll()
}
}
} else {
completion(false, 0.0)
}
}
// MARK: - Private - Refresh Tokens
private func refreshTokens(completion: @escaping RefreshCompletion) {
guard !isRefreshing else { return }
isRefreshing = true
let urlString = "\(baseURLString)/oauth2/token"
let parameters: [String: Any] = [
"access_token": accessToken,
"refresh_token": refreshToken,
"client_id": clientID,
"grant_type": "refresh_token"
]
sessionManager.request(urlString, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { [weak self] response in
guard let strongSelf = self else { return }
if
let json = response.result.value as? [String: Any],
let accessToken = json["access_token"] as? String,
let refreshToken = json["refresh_token"] as? String
{
completion(true, accessToken, refreshToken)
} else {
completion(false, nil, nil)
}
strongSelf.isRefreshing = false
}
}
}
Câu hỏi:
[weak self] succeeded, accessToken, refreshToken in
guard let strongSelf = self else { return }
mục đích
[weak self]
vàguard
chostrongSelf
là gì?requestsToRetry.append(completion) if !isRefreshing { refreshTokens { [weak self] succeeded, accessToken, refreshToken in guard let strongSelf = self else { return } //Implementation strongSelf.requestsToRetry.forEach { $0(succeeded, 0.0) } strongSelf.requestsToRetry.removeAll() } }
Yêu cầu này thử lại hoạt động như thế nào? Các
requestsToRetry
chỉ là một mảng củaRequestRetryCompletion = (_ shouldRetry: Bool, _ timeDelay: TimeInterval)
Làm thế nào để nó biết những gì yêu cầu thử lại?
strongSelf.lock.lock()
- Liệu
NSLock
chỉ không cho phépself
(OAuth2Handler) để được truy cập bởi bất kỳ thread khác trong khi phương pháp này được thực hiện?
1 để bạn có được tham chiếu mạnh mẽ đến 'tự' để mã sau không sử dụng' self' nếu nil của nó vì 'self' trong ngữ cảnh đó yếu, tham chiếu mạnh sẽ được phát hành ở cuối của phạm vi như vậy không có chu kỳ giữ lại sẽ xảy ra. Không quen thuộc với alamofire vì vậy không thể nói cho một số phần còn lại là gì. – Fonix