身份验证令牌

时间:2016-01-22 09:25:18

标签: siesta-swift

我正在尝试设置一个简单的iOS示例,以便更好地了解Siesta。我的REST api需要一个访问令牌来伴随每个请求。所以(1)在应用程序的开头和(2)我随时检索HTTP 401,我需要请求一个访问令牌,然后将其放在所有未来的授权头中。

从文档中解决这个例子,我假设包含showLoginScreen的行是我需要调用authenticationResource来检索令牌的地方但是我如何才能立即进行失败的调用(当然不是无限循环)?谢谢。

let authURL = authenticationResource.url

configure({ url in url != authURL }, description: "catch auth failures") {
  $0.config.beforeStartingRequest { _, req in  // For all resources except auth:
    req.onFailure { error in                     // If a request fails...
      if error.httpStatusCode == 401 {         // ...with a 401...
        showLoginScreen()                      // ...then prompt the user to log in
      }
    }
  }
}

1 个答案:

答案 0 :(得分:2)

由于您提出了问题,因此文档已使用an example that answers it进行了更新。

它的关键是使用decorateRequests(…)Request.chained(…)来包装所有服务的请求,以便它们在返回响应之前自动尝试刷新令牌。

以下是该示例中的代码:

authToken: String??

init() {
  ...
  configure("**", description: "auth token") {
    if let authToken = self.authToken {
      $0.headers["X-Auth-Token"] = authToken         // Set the token header from a var that we can update
    }
    $0.decorateRequests {
      self.refreshTokenOnAuthFailure(request: $1)
    }
  }
}

// Refactor away this pyramid of doom however you see fit
func refreshTokenOnAuthFailure(request: Request) -> Request {
  return request.chained {
    guard case .failure(let error) = $0.response,  // Did request fail…
      error.httpStatusCode == 401 else {           // …because of expired token?
        return .useThisResponse                    // If not, use the response we got.
    }

    return .passTo(
      self.createAuthToken().chained {             // If so, first request a new token, then:
        if case .failure = $0.response {           // If token request failed…
          return .useThisResponse                  // …report that error.
        } else {
          return .passTo(request.repeated())       // We have a new token! Repeat the original request.
        }
      }
    )
  }
}

func createAuthToken() -> Request {
  return tokenCreationResource
    .request(.post, json: userAuthData())
    .onSuccess {
      self.authToken = $0.jsonDict["token"] as? String  // Store the new token, then…
      self.invalidateConfiguration()                    // …make future requests use it
    }
  }
}