你的位置:首页 > ASP.net教程

[ASP.net教程]step_by_step_CSRF/ XSRF_问题描述


  接触Asp.net boilerplate 一段时间,一次同事将他的代码添加到zero项目模板中,他将路由配置成他的页面,目的是要让zero项目登录成功之后跳转到他的页面,可是通过fiddler监视请求报了一个错误

后来得知CSRF,翻阅下ABP Documents,了解下

  介绍

(CSRF)跨站点请求伪造 是一种恶意攻击,一个恶意网站,电子邮件,博客,或者应用程序导致一个已认证的用户在受信任的站点上执行一个不安全的操作(OWASP).

这里也简要的介绍了它在ASP.NET WEBAPI下如何实现

ABP架构尽可能多的去简化和自动化的完成CSRF防护,启动模板自带预定义配置和开箱即用,在本文中,我们将解释它是如何集成到ASP.NET平台并且了解它是如何工作的。

  HTTP动词

通常情况下,我们不需要保护GET,HEAD,OPTIONS和TRACE 这些HTTP操作,因为他们不会改变数据库,然而ABP假设(仅仅对POST,PUT,PATCH和DELETE这些HTTP动词进行保护),您也可以通过在文档中被定义的特性更改这一行为

ASP.NET MVC

特征

  正如你了解的那样,ASP.NET有它自己内置的防护系统,但是它有一些不足

  >在被保护的所有的ACTION上必须添加 ValidateAntiForgeryToken 注解,这样我们可能忘记在这些方法上添加此注解。

  >ValidateAntiForgeryToken 注解仅是检查表单的 _RequestVerificationToken 字段,这使得很难或者是不可能使用AJAX请求,尤其是如果你发送的请求的Content-Type 为 application/json,在AJAX中这通常是很常见的请求头。

  >这样在javascript代码中很难访问验证token(特别是如果你在.cshtml文件中不写javascript代码),在我们的AJAX请求中需要访问它

  >尽管我们用javascript可以访问到token,但是我们要为每次请求手动添加请求报文头

ABP做了以下的事情以应对这些困难

  >无需为POST,PUT,PATCH,DELETE添加 ValidateAniForgeryToken 注解,因为它们是自动的被保护(通过 AbpAntiForgeryMvcFilter),大多数情况下 自动保护 已经足够了,反之你也可以通过 DisableAbpAntiForgeryTokenValidation 注解 去禁用一个Action或者一个Controller,你也可以通过 ValidateAbpAntiForgeryToken 注解去启用一个Action或者一个Controller。

  > AbpAntiForgeryMvcFilter 除了表单字段之外还会检查请求头中的token,因此我们可以很容易的在AJAX请求中使用请求伪造保护。

  >提供了 abp.security.antiForgery.getToken()方法用javascript获取token ,甚至你不需要使用它。

  >为所有的AJAX请求头中自动的添加anti forgery token

因此,他几乎无缝协作。

整合

项目启动模板已经集成了开箱即用的CSRF防护,如果你要手动将它添加到你的项目中(也许你想要在创建项目之前添加它),下边将提供向导

模板视图

我们应该将以下代码添加到模板视图中

@{ SetAntiForgeryCookie(); }

因此,所有的页面使用这个布局页都将包含它,这个方法定义在视图基类中, 它创建并设置合适的cookie token ,用于工作中的javascript,如果你有多个布局页,添加它到所有页面。

这些就是我们应该为ASP.NET MVC所做的,所有的AJAX请求会自动工作,但是我们还是应该为不被配置的html表单使用 @Html.AntiForgeryToken() HTML帮助方法(但是不需要在对应的方法添加 ValidateAbpAntiForgeryToken 注解)。

配置

XSRF保护默认启用,你也可以在你的模块的预初始化方法中禁用它  ,例如:

1 Configuration.Modules.AbpWeb().AntiForgery.IsEnabled=false;

你还可以使用 Configuration.Modules.AbpWebCommon().AntiForgery 配置token和cookie的名字。

ASP.NET WEB API

特征

ASP.NET WEB API并不包含防伪造机制,Asp.net boilerplate 为ASP.NET提供了CSRF 防护的基础设施,以增加对ASP.NET WEBAPI完全自动化的CSRF保护。

集成

在 ASP.NET 客户端中

如何你在一个MVC项目中使用Web Api,无需增加额外的配置,甚至你在另外的进程中自托管你的Web Api 层,只要你从一个配置过的MVC应用程序中发送的AJAX请求,就无需配置。

在其他的客户端中

如何你的客户端是不同种类的应用程序(比如说,正如前面描述的单页面Angularjs应用程序,将不能使用 SetAntiForgeryCookie() 方法),这是应该提供一种设置anti frogery 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;    }  }}

然后你就可以在客户端调用这个方法去设置Cookie。

ASP.NET Core

ASP.NET Core 相比前一版本(ASP.NET MVC 5.x的)有更好的防伪造机制:

  >它有 AutoValidateAntiforgeryTokenAttribute 类,对所有的POST,PUT,PATCH和 DELETE操作有自动的防伪造验证。

  >存在 ValidateAntiForgeryToken 和IgnoreAntiforgeryToken 注解来控制token验证。

  >如果没有明确的禁用它,将自动添加token到你的表单中,所以大多数情况下不需要调用 @Html.AntiForgeryToken() 方法。

  >它可以在请求报文头和表单字段读取token。

ABP增加了以下功能:

  >自动的为所有AJAX请求添加防伪造token 。

  >还在javascript中提供了 abp.security.antiForgery.getToken()方法来得到token ,尽管你不需要它。

集成

启动模板已经集成了开箱即用的CSRF防护,如果您需要手动添加到您的项目中(也许你的项目在我们添加它之前创建),请参照指南。

启动类

首先,我们应该在启动类 ConfigureServices 中加入MVC的同时 并将 AutoValidateAntiforgeryTokenAttribute 添加到全局过滤器 :

1 services.AddMvc(options =>2 {3   options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());4 });

这样,所有的MVC 动作(除了GET,HEAD,OPTIONS和TRACE正如之前的那些)都会自动验证token 。

布局视图

我们应该在布局视图上添加以下代码:

@using Abp.Web.Security.AntiForgery@inject IAbpAntiForgeryManager AbpAntiForgeryManager@{  AbpAntiForgeryManager.SetCookie(Context);}

因此所有的页面使用布局页也将包含它,同样这个方法也是ABP视图基类中定义的,它创建并设置合适的token cookie,在javascript端工作,如果你有多个布局页面,同样将这些添加到这些页面上。

这些就是我们应该为ASP.NET CORE 所做的所有的AJAX请求都会自动的执行,而对于非AJAX 的表单提交,如果你在表单中使用Asp-*的标签,ASP.NET CORE 会自动的为表单添加防伪造token,所以正常情况下不需要使用 @Html.AntiForgeryToken() 方法。

客户端库

正如我们之前声明的那样,防伪造token应该在所有的AJAX请求头中被加入,我们将看到他是如何完成的。

jQuery

abp.jquery.js 为每一个在请求头添加token的请求定义了一个拦截器,它从这个 abp.security.antiForgery.getToken()  javascript 方法中获取token。

Angularjs

Angularjs 会自动添加防伪造token到所有的AJAX请求,详见Angualrjs 文档 :跨站请求伪造(XSRF)保护。ABP默认使用相同的cookie和头文件名。因此,Angularjs 整合工作开箱即用。

其他库

如何你为AJAX 请求使用任何其他的库,你有三种选择:

拦截

由于所有的库使用javascript 的本地 AJAX对象,

1 (function (send) {2    function (data) {3     this.setRequestHeader(abp.security.antiForgery.tokenHeaderName, abp.security.antiForgery.getToken());4     return send.call(this, data);5   };6 })(

使用库拦截器

一个好的库应该提供拦截点(像jQuery和Angularjs)。所以应该按照你供应商的文档并了解如何拦截请求和操作报文头。

手动添加报文头

最后的操作,你也可以通过使用abp.security.antiForgery.getToken() 方法来 获得token并且可以手动添加到请求头中。但是你可能并不需要这么做,可以通过前面描述的那样解决问题。

本质

你可能想了解ABP如何处理它。事实上,我们使用之前提到的Angualrjs文档提到相同的机制。ABP在cookie中存储token(如上所述),并设置请求头,这也很好的与ASP.NET MVC ,ASP.NET WEB API,CORE FRAMEWORK结合在一起进行验证。