[水煮 ASP.NET Web API2 方法論](1-7)CSRF-Cross-Site Request Forgery

来源:http://www.cnblogs.com/shuizhucode/archive/2016/11/16/6068086.html
-Advertisement-
Play Games

問題 通過 CSRF(Cross-Site Request Forgery)防護,保護從 MVC 頁面提交到ASP.NET Web API 的數據。 解決方案 ASP.NET 已經加入了 CSRF 防護功能,只要通過 System.web.Helpers.AntiForgery 類(System.W ...


問題

  通過 CSRFCross-Site Request Forgery)防護,保護從 MVC 頁面提交到ASP.NET Web API 的數據。

 

解決方案

  ASP.NET 已經加入了 CSRF 防護功能,只要通過 System.web.Helpers.AntiForgery 類(System.Web.WebPages 的一部分)就可以。

他會生成兩個 Token

  • Cookie Token

  • 基於字元串的 Token

  基於字元串的 Token 是可以嵌入到表單或者請求頭(使用 Ajax 的情況下)。為了防止 CSRF 攻擊,表單提交和Ajax 請求到 API 的數據必須包含這些Token,伺服器將會驗證這兩個 Token

  在 ASP.NET Web APIanti-CSRF Token 驗證是一個典型的實現了橫切關係的 MessageHandler

 

工作原理

  為了能在 MVC 應用程式的上下文中生成 Token,我們必須在表單中調用一個叫做 AntiForgeryToken HtmlHelper 的擴展方法。

 

1 2 3 4 <form id="myForm">     @Html.AntiForgeryToken()     @* 其他標簽 *@ </form>

 

  這個幫助方法在AntiForgery 類中。他會寫一個 Token 到響應的 Cookie 中,同時生成一個名字叫做_RequestVerificationToken 的欄位,也會隨著表單數據同時被提交。

  為能在伺服器端驗證 Token,我們可以通過調用AntiForgery 類的靜態方法 Validate 來驗證。如果調用的時候沒有傳遞參數的話,就會從 HttpContext.Current 中試著獲取相關的 Cookie 和請求體中提取 Token,在這裡,我們假設確實有一個 Body 並且 Body 中也有一個 _RequestVerificationToken

  由於這個方法是 void (無返回值)的,所以,請求驗證成功後,方法什麼反饋也沒有,如果失敗,就會拋HttpAntiForgeryException 的異常。我們可以捕獲這個異常,然後返回給客戶端相應的響應(例如,一個 HTTP 403 的狀態碼)。

  有一個可替代的方式就是調用 Validate 方法,我們自己來傳這兩個 Token。這時候,就要從 Request 中獲取這兩個值。例如,可能是在 Header 中。這種方式也可以擺脫對 HttpContext 的依賴。

  對於 Web API,我們可以自定義消息處理器,在每個請求進入 Web API 的時候來負責 CSRF Token 的驗證,執行必要的驗證,然後繼續管道執行,或者,在請求無效的情況下,直接短路錯誤響應(也就是說,立即返回錯誤碼)。

 

代碼演示

  我們來演示 MessageHandler 執行 CSRF 驗證的例子如清單 1-23 所示。

  兩種方式:

  1.  Ajax 請求。

  2. 用其他的請求。

  我們都簡單假設他們都是表單提交的。如果是一個 Ajax 請求,我們可以嘗試著從請求 Header 中獲取Token,同時,可以從與 Request 一同提交的 Cookie 集合中獲取Cookie Token,然後,使用無參的 Validate方法驗證,這樣,就需要我們自己來提取 Token

  如果驗證失敗,客戶端會得到一個 403 的錯誤響應。

 

清單 1-23. Anti_CSRF 消息處理器

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class AntiForgeryHandler : DelegatingHandler {     protected override async Task<HttpResponseMessage> SendAsync(     HttpRequestMessage request,     CancellationToken cancellationToken)     {         string cookieToken = null;         string formToken = null;         if (request.IsAjaxRequest())         {             IEnumerable<string> tokenHeaders;             if (request.Headers.TryGetValues("__RequestVerificationToken"out tokenHeaders))             {                 var cookie = request.Headers.GetCookies(AntiForgeryConfig.CookieName).                 FirstOrDefault();                 if (cookie != null)                 {                     cookieToken = cookie[AntiForgeryConfig.CookieName].Value;                 }                 formToken = tokenHeaders.FirstOrDefault();             }         }         try         {             if (cookieToken != null && formToken != null)             {                 AntiForgery.Validate(cookieToken, formToken);             }             else             {                 AntiForgery.Validate();             }         }         catch (HttpAntiForgeryException)         {             return request.CreateResponse(HttpStatusCode.Forbidden);         }         return await base.SendAsync(request, cancellationToken);     } }

 

  我們還需要在 API HttpConfiguration 中註冊,這樣才會在全局起作用。

 

1 config.MessageHandlers.Add(new AntiForgeryHandler());

 

  構築一個 anti-CSRF 護盾作為消息處理器並不是唯一方式。我們也可以在過濾器內部使用同樣的代碼,然後將過濾器應用到相應的 Action 上(類似的,怎麼用過濾器驗證,我們將在 5-4 詳細討論)。如果消息處理器不是全局使用,也可以附加到指定路由上。我們將在 3-9 詳細討論這一塊兒。

  HttpRequestMessage有一個內建的方式來檢查是否為 Ajax 請求,就是用一個簡單的擴展方法來實現,他依賴於 Header  X-Requested-With,大多數的 JavaScript 框架都會自動發送這個在 Header 中。這個方法如清單1-24 所示。

 

清單 1-24. 檢查 HttpRequestMessage 是否為一個 Ajax 請求的擴展方法。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static class HttpRequestMessageExtensions {     public static bool IsAjaxRequest(this HttpRequestMessage request)     {         IEnumerable<string> headers;         if (request.Headers.TryGetValues("X-Requested-With"out headers))         {             var header = headers.FirstOrDefault();             if (!string.IsNullOrEmpty(header))             {                 return header.ToLowerInvariant() == "xmlhttprequest";             }         }         return false;     } }

 

  清單 1-25 展示了,傳統表單提交和 Ajax 請求都利用 anti-CSRF Token 的例子。在傳統表單提交的情況下,HTML helper 會生成一個隱藏域,同時,anti-forgery token 會隨著表單一塊兒被自動提交。在 Ajax 請求的情況下,我們顯示的從隱藏域中讀取 Token,然後,將其附加到請求頭中。

 

清單 1-25. 傳統表單和 Ajax 請求方式下,提交數據到 ASP.NET WEB API 使用 Anti-CSRF 防護

//HTML表單

1 2 3 4 5 6 7 8 9 10 11 12 <form id="form1" method="post" action="/api/form" enctype="application/x-www-form-urlencoded">     @Html.AntiForgeryToken()     <div>         <label for="name">Name</label>     </div>     <div>         <input type="text" name="name" value="Some Name" />     </div>     <div>         <button id="postData" name="postData">Post form</button>     </div> </form>

 

// Ajax 表單

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Html.AntiForgeryToken() <input id="itemJS" type="text" disabled="disabled" name="text" value="some text" /> <div>     <button id="postJS" name="postJS">Post JS</button> </div> <script type="text/javascript">     $(function () {         $("#postJS").on("click", function () {             $.ajax({                 dataType: "json",                 data: JSON.stringify({ name: $("#itemJS").val() }),                 type: "POST",                 headers: {                     "__RequestVerificationToken": $("#jsData input[name='__                     RequestVerificationToken']").val()                 },                 contentType: "application/json; charset=utf-8",                 url: "/api/items"             }).done(function (res) {                 alert(res.Name);             });         });     }); </script>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有用戶反映,Tausus.MVC 能寫WebAPI麽?能!教程呢?嗯,木有-_-!好吧,剛好2.0出來,就帶上WEBAPI教程了! ...
  • 本節內容: 顯示信息 確認 Message API給用戶顯示一個信息,或從用戶那裡獲取一個確認信息。 Message API預設使用sweetalert實現,為使sweetalert正常工作,你應該包含它的css和javascript文件,然後把abp.sweet-alert.js適配器包含到你的頁 ...
  • 首先創建一個C# 控制台應用程式, 直接伺服器端代碼丟進去,然後再到Unity 裡面建立一個工程,把客戶端代碼掛到相機上,運行服務端,再運行客戶端。 高手勿噴!~! 完全源碼已經奉上,大家開始研究吧!! 嘎嘎嘎! 服務端代碼:Program.cs using System; using System ...
  • 網路爬蟲在信息檢索與處理中有很大的作用,是收集網路信息的重要工具。 接下來就介紹一下爬蟲的簡單實現。 爬蟲的工作流程如下 爬蟲自指定的URL地址開始下載網路資源,直到該地址和所有子地址的指定資源都下載完畢為止。 下麵開始逐步分析爬蟲的實現。 1. 待下載集合與已下載集合 為了保存需要下載的URL,同 ...
  • 介紹C#如何對ini文件進行讀寫操作,C#可以通過調用【kernel32.dll】文件中的 WritePrivateProfileString()和GetPrivateProfileString()函數分別對ini文件進行讀和寫操作。包括:讀取key的值、保存key的值、讀取所有section、讀取... ...
  • 剛開始接觸Nop的盆友們,肯定會遇到很多問題,在這,介紹下會經常遇到的問題。 一:後臺無法打開 原因:只生成了web,要把整個項目都生成下。 ~資料還在整理中~ ...
  • Nop里自帶的只有國家、省份,在國內是不夠的,得加上城市、地區。 本來想把代碼放上來的,可是,得改一天,新增和修改的代碼量可想而知了,只能說,國家、省份有了,參考來做城市、地區,也不是很難,不過很是繁瑣。 來點福利壓壓驚,NopAddressData.xml ...
  • using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;using System.Text;namespace HttpDemo{ class Program { ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...