返回总目录
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有自己内置的反伪造系统,但它有一些不足:
ABP做了下面这些事情来客服上面的困难:
启动模板已经集成了现成的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不包括反伪造机制,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了。
abp.jquery.js中定义了一个ajax拦截器,它可以将反伪造请求token添加到每个请求的请求头中,它会从abp.security.antiForgery.getToken()函数中获得token。
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框架。