ASP.NET Web API(三):安全驗證之使用摘要認證(digest authentication)

來源:互聯網
上載者:User

標籤:web   使用者資訊   原始碼   大致   方法   服務   linq   cat   can   

在前一篇文章中,主要討論了使用HTTP基本認證的方法,因為HTTP基本認證的方式決定了它在安全性方面存在很大的問題,所以接下來看看另一種驗證的方式:digest authentication,即摘要認證。

系列文章列表

ASP.NET Web API(一):使用初探,GET和POST資料
ASP.NET Web API(二):安全驗證之使用HTTP基本認證
ASP.NET Web API(三):安全驗證之使用摘要認證(digest authentication)

摘要認證原理

在基本認證的方式中,主要的安全問題來自於使用者資訊的明文傳輸,而在摘要認證中,主要通過一些手段避免了此問題,大大增加了安全性。

為摘要驗證的驗證原理流程圖。

下面大致看一下這部分的驗證流程:

  1. 用戶端請求 /api/employees;
  2. 服務端返回401未驗證的狀態,並且在返回的資訊中包含了驗證方式Digest,realm的值,QOP(quality of protection)只設定成auth,nonce為一串隨機值,在下面的請求中會一直使用到,當過了存活期後服務端將重新整理產生一個新的nonce值;
  3. 用戶端接受到請求返回後,將username:realm:password進行HASH運算,假設運算後的值為HA1。又將請求的路徑/api/employees進行HASH運算,假設運算後的值為HA2。再將HA1:nonce:nc:cnonce:qop:HA2進行HASH運算,得到的值放在response中。這裡的cnonce為用戶端產生的nonce值,而nc用於統計,假設開始時為00000001,下次請求後就變成了00000002,不一定每次都加1,但是後面請求中的nc值肯定大於前一次請求中的nc值。
  4. 服務端收到請求後將驗證nonce是否到期,如果到期,那麼直接返回401,即第二步的狀態。如果沒有到期,那麼比較nc值,如果比前一次nc值小或者前一次根本沒有儲存的nc值,那麼也將直接返回401狀態。如果前面的驗證都通過,那麼服務端也將按照步驟3中計算最終HASH值的步驟計算出HASH值與用戶端的進行比較,然後比較用戶端提交過來的HASH值與服務端計算出來的HASH進行比較,不匹配返回401,匹配擷取請求的資料並返回狀態200。

摘要驗證主要就是通過上面的HASH比較的步驟避免掉了基本驗證中的安全性問題。

需要注意的是,如果需要IIS支援摘要驗證,需要把IIS摘要驗證的特性勾上。

摘要驗證的實現

在理解了摘要驗證的原理之後,只需要用代碼實現即可。

判斷nonce是否到期的方法。

 1         public static bool IsValid(string nonce, string nonceCount) 2         { 3             Tuple<int, DateTime> cachedNonce = null; 4             nonces.TryGetValue(nonce, out cachedNonce); 5  6             if (cachedNonce != null) // nonce is found 7             { 8                 // nonce count is greater than the one in record 9                 if (Int32.Parse(nonceCount) > cachedNonce.Item1)10                 {11                     // nonce has not expired yet12                     if (cachedNonce.Item2 > DateTime.Now)13                     {14                         // update the dictionary to reflect the nonce count just received in this request15                         nonces[nonce] = new Tuple<int, DateTime>(Int32.Parse(nonceCount),16                                                                                                             cachedNonce.Item2);17 18                         // Every thing looks ok - server nonce is fresh and nonce count seems to be 19                         // incremented. Does not look like replay.20                         return true;21                     }22                 }23             }24 25             return false;26         }
判斷nonce是否到期的代碼

下面為摘要驗證實現的核心方法

 1 namespace DigestAuthentication 2 { 3     public class AuthenticationHandler : DelegatingHandler 4     { 5         protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 6         { 7             try 8             { 9                 var headers = request.Headers;10                 if (headers.Authorization != null)11                 {12                     Header header = new Header(request.Headers.Authorization.Parameter,13                                                                                                                       request.Method.Method);14 15                     if (Nonce.IsValid(header.Nonce, header.NounceCounter))16                     {17                         // Just assuming password is same as username for the purpose of illustration18                         string password = header.UserName;19 20                         string ha1 = String.Format("{0}:{1}:{2}", header.UserName, header.Realm,21                                                                                                                              password).ToMD5Hash();22 23                         string ha2 = String.Format("{0}:{1}", header.Method, header.Uri).ToMD5Hash();24 25                         string computedResponse = String26                                       .Format("{0}:{1}:{2}:{3}:{4}:{5}",27                                             ha1, header.Nonce, header.NounceCounter,28                                                                                          header.Cnonce, "auth", ha2).ToMD5Hash();29 30                         if (String.CompareOrdinal(header.Response, computedResponse) == 0)31                         {32                             // digest computed matches the value sent by client in the response field.33                             // Looks like an authentic client! Create a principal.34                             var claims = new List<Claim>35                             {36                                             new Claim(ClaimTypes.Name, header.UserName),37                                             new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Password)38                             };39 40                             var principal = new ClaimsPrincipal(new[] { new ClaimsIdentity(claims, "Digest") });41 42                             Thread.CurrentPrincipal = principal;43 44                             if (HttpContext.Current != null)45                                 HttpContext.Current.User = principal;46                         }47                     }48                 }49 50                 var response = await base.SendAsync(request, cancellationToken);51 52                 if (response.StatusCode == HttpStatusCode.Unauthorized)53                 {54                     response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Digest",55                                                                                      Header.UnauthorizedResponseHeader.ToString()));56                 }57 58                 return response;59             }60             catch (Exception)61             {62                 var response = request.CreateResponse(HttpStatusCode.Unauthorized);63                 response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Digest",64                                                                                        Header.UnauthorizedResponseHeader.ToString()));65 66                 return response;67             }68         }69     }70 71 }
摘要驗證實現的核心方法

實現完成後,使用摘要驗證只需要在對應的方法加上[Authorize]屬性標籤即可。

摘要驗證的優缺點

摘要驗證很好地解決了使用基本驗證所擔心的安全性問題。

但是永遠沒有絕對的安全,當使用者使用字典進行窮舉破解時,還是會存在一些被破解的隱患。

源碼下載

編輯器裡怎麼找不到上傳檔案的地方了?我上傳到了百度網盤裡。

原始碼下載

參考頁面:http://qingqingquege.cnblogs.com/p/5933752.html

ASP.NET Web API(三):安全驗證之使用摘要認證(digest authentication)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.