2012-01-27 54 views
1

我正在使用REST API,如果我的授權令牌已過期,它將返回401。當我收到401時,我想運行我的驗證邏輯,檢索一個新的令牌,然後重試我的原始呼叫。什麼是最好的方式來做到這一點。如何使用Web服務重新進行身份驗證,然後重試REST調用

現在,我有一個Authenticator類「知道」如何使用API​​進行身份驗證。數據訪問邏輯的其餘部分位於Repository對象中。 Repository對象有責任使用存儲在Authenticator中的信息向API發送請求以檢索信息。

一個這樣的例子是Repository.List()[它不是真的靜態的,只是爲了簡潔而寫它。從概念上講,這是List()應該做的事情。

  • 嘗試連接到API並獲得項目的列表
  • 如果401錯誤,重新認證,然後再試一次
  • 返回的項目列表或拋出一個異常

這種模式將用於我所有存儲庫中的所有方法,所以我想要一個委託或我可以用於所有API調用的東西。

任何想法?

感謝, 格雷格

回答

1

我想出了運作良好的解決方案。

我創建了一個靜態方法,它接受兩個參數,一個Func和一個對我的 認證對象的引用。 Authentication對象可以重新進行身份驗證,並保存用於進行API調用的身份驗證信息。我使用了ref,因爲我不希望一個帳戶的Authenticator的多個實例存在不同的驗證令牌,但我需要能夠同時支持多個帳戶,所以我無法將其設置爲靜態。

public static string ReauthenticateOn401(
    Func<Authenticator, string> method, 
    ref Authenticator authenticator) 
{ 
    if (method == null) 
     throw new ArgumentNullException("action"); 

    if (authenticator == null) 
     throw new ArgumentNullException("authenticator"); 

    int attempts_remaining = 2; 
    bool reauth_attempted = false; 
    while (attempts_remaining > 0) 
    { 
     try 
     { 
      return method(authenticator); 
     } 
     catch (WebException e) 
     { 
      if (e.Response != null && reauth_attempted == false) 
      { 
       if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.Unauthorized) 
       { 
        authenticator.GetAuthToken(); 
        reauth_attempted = true; 
        attempts_remaining--; 
       } 
       else 
       { 
        throw; 
       } 
      } 
      else 
      { 
       throw; 
      } 
     } 
    } 
    throw new Exception("The ReauthenticateOn401 method failed to return a response or catch/throw an exception. The log flowed outside the while loop (not expected to be possible) and is generating this generic exception"); 
     } 

然後我有不同的類來從API請求數據。以下是其中一個可能的樣子,其中_authenticator在類實例化時被傳遞到類中。

string json = Authenticator.ReauthenticateOn401((authenticator) => 
{ 
    string apiUrl = "http:/blahblahblah.api.com" 
    HttpWebRequest request = WebRequest.Create(apiUrl) as HttpWebRequest; 
    //Add headers, or adjust the body as necessary for your API 
    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) 
    using (StreamReader reader = new StreamReader(response.GetResponseStream())) 
    { 
     return reader.ReadToEnd(); 
    } 
}, ref _authenticator); 

的美妙之處在於,我可以在任何邏輯我想ReathenticateOn401通過,它將嘗試調用該方法,然後如果接收到401重新驗證。否則,它會成功或拋出我可以處理的異常。

相關問題