"返回總目錄" 本篇目錄 "介紹" "ASP.NET MVC" "ASP.NET WEB API" "ASP.NET Core" 【以後補上】 "客戶端類庫" "內部原理" 介紹 CSRF【Cross Site Request Forgery】 跨站請求偽造是一種攻擊類型,一般指的是一個惡意的網站、 ...
本篇目錄
介紹
CSRF【Cross-Site Request Forgery】跨站請求偽造是一種攻擊類型,一般指的是一個惡意的網站、郵件、博客、即時消息、或程式使得用戶的web瀏覽器對當前用戶已認證的可信任網站執行一個自己不願執行的操作。想要詳細瞭解的可以查看百度CSRF,擴展閱讀OWASP。
這裡簡明描述一下如何在ASP.NET Web API中實現。
ABP框架儘可能地簡化並 自動化了CSRF保護,現成的啟動模板已經做了預配置。本文,會解釋如何將它集成到ASP.NET平臺的,以及它是如何工作的。
HTTP動詞
無需對GET,HEAD,OPTIONS,TRACEHTTP動詞做保護操作,因為正常情況下它們應該是無副作用的(不會更改資料庫)。ABP只對POST,PUT,PATCH,DELETE動詞實現了反偽造(Anti-Forgery)保護,可以使用本文中定義的特性來更改該行為。
ASP.NET MVC
功能
大家都知道,ASP.NET MVC有自己內置的反偽造系統,但它有一些不足:
- 需要為保護的所有actions添加ValidateAntiForgeryToken特性,這個容易忘記。
- ValidateAntiForgeryToken特性只檢查HTML 表單域中的**__RequestVerificationToken,這就使得在AJAX請求中使用它非常困難或不可能,尤其是以"application/json"**作為content-type發送請求時。在Ajax請求中,通常會在請求頭中設置token。
- 在JS代碼中很難訪問驗證token,尤其是不在.cshtml文件中寫JS。但我們需要在AJax請求中訪問使用。
- 即使可以在js中訪問token,也需要為每個請求都在頭部手動加入,很是麻煩。
ABP做了下麵這些事情來客服上面的困難:
- actions會被自動保護(通過AbpAntiForgeryMvcFilter)。自動保護可以應對大多數情況。當然,可以使用DisableAbpAntiForgeryTokenValidation特性為任何action和Controller關閉自動保護,也可以使用 ValidateAbpAntiForgeryToken特性打開。
- 除了HTML的表單域,AbpAntiForgeryMvcFilter也會檢查請求頭中的token。因此,可以很容易對ajax請求使用反偽造token保護。
- 在js中可以使用abp.security.antiForgery.getToken()函數獲得token。
- 為所有的ajax請求頭部自動添加反偽造token。
集成
啟動模板已經集成了現成的CSRF保護,如果需要手動將它添加到你的項目,那麼請參照以下步驟。
Layout 視圖
在Layout視圖中添加以下代碼:
@{
SetAntiForgeryCookie();
}
這樣,所有使用了這個佈局頁的頁面都會包含這句代碼了,該方法定義在ABP視圖基類中,它會創建和設置正確的token cookie,使得在js端可以工作。如果有多個Layout的話,需要為每個佈局添加上面的代碼。
對於ASP.NET MVC 應用,只需要做這麼多,所有的ajax請求都會自動工作。但是對於HTML 表單仍然需要使用** @Html.AntiForgeryToken()** HTML幫助方法,因為表單不是通過Ajax提交的,但是不需要在相應的action上使用ValidateAbpAntiForgeryToken 特性了。
配置
XSRF預設是打開的,也可以在模塊的PreInitialize方法中關閉或配置,如下:
Configuration.Modules.AbpWeb().AntiForgery.IsEnabled = false;
也可以使用Configuration.Modules.AbpWebCommon().AntiForgery對象配置token和cookie名稱。
ASP.NET WEB API
功能
ASP.NET Web API不包括反偽造機制,ABP為ASP.NET Web API Controllers提供了基礎設施來添加CSRF保護,並且是完全自動化的。
集成
ASP.NET MVC客戶端
如果在MVC項目中使用了Web API,那麼不需要額外的配置。只要Ajax請求是從一個配置的MVC應用中發出的,即使你的Web API層自宿主在其它進程中,也不需要配置。
其它客戶端
如果你的客戶端是其它類型的應用(比如,一個獨立的angularjs應用,它不能像之前描述的那樣使用SetAntiForgeryCookie()方法),那麼你應該提供一種設置反偽造token cookie的方法。一種可能的實現方式是像下麵那樣創建一個api控制器:
using System.Net.Http;
using Abp.Web.Security.AntiForgery;
using Abp.WebApi.Controllers;
namespace AngularForgeryDemo.Controllers
{
public class AntiForgeryController : AbpApiController
{
private readonly IAbpAntiForgeryManager _antiForgeryManager;
public AntiForgeryController(IAbpAntiForgeryManager antiForgeryManager)
{
_antiForgeryManager = antiForgeryManager;
}
public HttpResponseMessage GetTokenCookie()
{
var response = new HttpResponseMessage();
_antiForgeryManager.SetCookie(response.Headers);
return response;
}
}
}
然後就可以從客戶端調用這個action來設置cookie了。
ASP.NET Core###【以後補上】
客戶端類庫
jQuery
abp.jquery.js中定義了一個ajax攔截器,它可以將反偽造請求token添加到每個請求的請求頭中,它會從abp.security.antiForgery.getToken()函數中獲得token。
Angularjs
Angularjs會將反偽造token自動添加到所有的ajax請求中,請點擊鏈接查看Angularjs的XSRF保護一節。ABP預設使用了相同的cookie和header名稱。因此,Angularjs集成是現成可用的。
其它類庫
如果你使用了其它類庫做Ajax請求,那麼有三種選擇:
Intercept XMLHttpRequest
因為所有的類庫都使用了原生的js Ajax對象——XMLHttpRequest,因此可以定義一個簡單的攔截器,將token添加到請求頭部:
(function (send) {
XMLHttpRequest.prototype.send = function (data) {
this.setRequestHeader(abp.security.antiForgery.tokenHeaderName, abp.security.antiForgery.getToken());
return send.call(this, data);
};
})(XMLHttpRequest.prototype.send);
Use Library Interceptor
好的類庫都會提供攔截點(比如 jquery和angularjs),因此,請查看文檔學習如何攔截請求以及操作頭部。
Add the Header Manually
最後,可以使用abp.security.antiForgery.getToken()獲取token,然後手動為每個請求添加請求頭,但是很可能不需要這麼做,而是按照上面的方法解決問題。
內部原理
你可能想知道ABP是如何處理這個的,實際上,ABP使用了和之前文檔描述的angularjs機制是一樣的。ABP會將token保存到一個cookie中,然後使用那個cookie設置請求頭。這個實現也很好地集成到了ASP.NET MVC, Web API 和 Core框架。