ABP框架系列之五十四:(XSRF-CSRF-Protection-跨站请求伪造保护)
Introduction
"Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated" (OWASP).
It's also briefly described here to explain how to implement it in ASP.NET Web API.
ABP framework simplifies and automates CSRF protection as much as possible. Startup templates comes with pre-configured and working out of the box. In this document, we will explain how it's integrated to ASP.NET platforms and how it works.
“跨站请求伪造(CSRF)是一种类型的攻击时,一个恶意网站、电子邮件、博客、即时消息、或程序导致用户的Web浏览器来执行必要的行动在一个受信任的站点,用户目前认证”(OWASP)。
它也作了简要的叙述来说明如何实现它在ASP.NET Web API。
ABP框架简化并自动化CSRF保护尽可能多的。启动模板附带预配置和已完成的框。在本文档中,我们将解释它是如何集成到ASP.NET平台和它是如何工作的。
Http Verbs
It's not needed to protect our actions for GET, HEAD, OPTIONS and TRACE HTTP verbs since they should be side effect free (don't change database) normally. While ABP assumes that (and implements Anti Forgery protection for only POST, PUT, PATCH and DELETE verbs), you can change this behaviour using attrbiutes defined in this document.
不必保护GET, HEAD, OPTIONS and TRACE这些http谓词,因为正常情况下应该是无副作用的。(不改变数据库),ABP假如(实现了POST, PUT, PATCH and DELETE的防伪保护),你可以使用本文档中的特性改变行为。
Non Browser Clients(非浏览器的客户端)
CSRF is a type of attack that is a problem for browsers. Because a browser sends all cookies (including auth cookies) in all requests, including cross domain requests. But, it's not a problem for non browser clients, like mobile applications. ABP framework can understand the difference and automatically skips anti forgery validation for non browser clients.
CSRF攻击类型,是浏览器的问题。因为一个浏览器发送的所有cookies(包括认证cookies)在所有的要求,包括跨域请求。但是,对于非浏览器客户来说,这不是问题,比如移动应用程序。ABP框架可以理解这种差异,并自动跳过非浏览器客户端的防伪验证。
ASP.NET MVC
Features
ASP.NET MVC has it's own built-in AntiForgery system as you probably know. But it has a few weeknesses:
- Requires to add ValidateAntiForgeryToken attribute to all actions need to be protected. We may forget to add it for all needed actions.
- ValidateAntiForgeryToken attribute only checks __RequestVerificationToken in the HTML form fields. This makes very hard or impossible to use it for AJAX requests, especially if you are sending "application/json" as content-type. In AJAX requests, it's common to set token in the request header.
- It's hard to access to the verification token in javascript code (especially if you don't write your javascript in .cshtml files). We need to access it to use it in our AJAX requests.
- Even we can access to the token in javascript, we should manually add it to the header for every request.
ASP.NET MVC有它自己的内置防伪系统,正如你可能知道的。但是它有几个薄弱环节:
需要添加validateantiforgerytoken属性的所有动作都需要被保护。我们可能忘记为所有需要的行动添加它。
validateantiforgerytoken属性只检查__requestverificationtoken在HTML表单字段。这很难或不可能将它用于Ajax请求,尤其是当您将“应用程序/ JSON”作为内容类型发送时。在ajax请求中,在请求标头中设置令牌是很常见的。
使用JavaScript代码验证令牌是困难的(尤其是如果你不写你的JavaScript。cshtml文件)。我们需要访问它来在Ajax请求中使用它。
即使我们可以用JavaScript访问令牌,我们也应该手动将它添加到每个请求的报头中。
ABP does followings to overcome this difficulties:
- No need to add ValidateAntiForgeryToken attribute for POST, PUT, PATCH and DELETE actions anymore, because they are automatically protected (by AbpAntiForgeryMvcFilter). Automatic protection will be enough for most cases. But you can disable it for an action or controller using DisableAbpAntiForgeryTokenValidation attribute and you can enable it for any action/controller using ValidateAbpAntiForgeryTokenattribute.
- AbpAntiForgeryMvcFilter also checks token in the header in addition to HTML form field. Thus, we can easily use anti forgery token protection for AJAX requests.
- Provides abp.security.antiForgery.getToken() function to get the token in the javascript, even you will not need it much.
- Automatically adds anti forgery token to the header for all AJAX requests.
ABP采取以下措施来克服这些困难:
不需要添加后,validateantiforgerytoken属性,补丁和删除动作了,因为他们是自动保护(AbpAntiForgeryMvcFilter)。大多数情况下自动保护就足够了。但是,您可以禁用它的一个动作或使用disableabpantiforgerytokenvalidation属性控制器,你可以使它对任何行动/控制器使用validateabpantiforgerytokenattribute。
abpantiforgerymvcfilter还检查除了HTML表单字段的标题标记。因此,我们可以很容易地使用Ajax请求的防伪令牌保护。
提供ABP。安全。防伪。gettoken()函数在JavaScript得到令牌,即使你不需要它。
为所有Ajax请求自动添加反令牌到报头。
Thus, it almost seamlessly works.
Integration
Startup templates already integrated to CSRF protection out of the box. If you need to manually add it to your project (maybe you created your project before we added it), follow this guide.
启动模板已集成CSRF保护开箱。如果需要手动将其添加到项目中(可能在添加项目之前创建了项目),请遵循本指南。
Layout View(布局视图)
We should add the following code in our Layout view:
@{ SetAntiForgeryCookie(); }
Thus, all pages use this layout will include it. This method is defined in base ABP view class. It creates and sets appropriate token cookies and makes javascript side working. If you have more than one layout, add this to all of them.
That's all we should do for ASP.NET MVC applications. All AJAX requests will work automatically. But we should still use @Html.AntiForgeryToken() HTML helper for our HTML forms which are not posted via AJAX (But no need to ValidateAbpAntiForgeryToken attribute for the corresponding action).
因此,所有使用此布局的页面都将包含它。这个方法是在基本视图视图类中定义的。它创建并设置适当的令牌cookie并使JavaScript侧工作。如果您有不止一个布局,请将其添加到所有这些布局中。
这是我们应该做的是ASP.NET的MVC应用程序。所有Ajax请求都将自动工作。但我们仍应使用“HTML。antiforgerytoken() HTML辅助我们的HTML表单不贴通过AJAX(但不需要validateabpantiforgerytoken属性相应的动作)。
Configuration
XSRF protection is enabled by default. You can disable or configure it in your module's PreInitialize method. Example:
XSRF保护默认情况下启用。您可以禁用或在你的模块的配置分发方法。例子:
Configuration.Modules.AbpWeb().AntiForgery.IsEnabled = false;
You can also configure token and cookie names using Configuration.Modules.AbpWebCommon().AntiForgery object.
ASP.NET Web API
Features
ASP.NET Web API does not include an anti forgery mechanism. ASP.NET Boilerplate provides infrastructure to add CSRF protection for ASP.NET Web API Controllers and completely automates it.
ASP.NET Web API不包括防伪机制。ASP.NET样板来添加ASP.NET Web API控制器CSRF保护提供了基础设施和完全自动化。
Integration
With ASP.NET MVC Clients
If you are using Web API inside an MVC project, no additional configuration needed. Even if you are self-hosting your Web API layer in another process, no configuration needed as long as you are making AJAX requests from a configured MVC application.
如果在MVC项目中使用Web API,则不需要额外的配置。即使您在另一个进程中自己托管Web API层,只要您从配置的MVC应用程序中生成Ajax请求,就不需要配置。
With Other Clients
If your clients are diffrent kind of applications (say, an independent angularjs application which can not use SetAntiForgeryCookie() method as described before), then you should provide a way of setting the anti forgery token cookie. One possible way of doing that is to create an api controller like that:
如果你的客户是不同类型的应用程序(比如说,一个独立的AngularJS应用不能使用setantiforgerycookie()方法如前所述),那么你应该提供一种方式来设置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; } } }
Then you can call this action from client to set the cookie.
然后,您可以从客户端调用此操作来设置cookie。
ASP.NET Core
Features
ASP.NET Core MVC has a better Anti Forgery mechanism compared to previous version (ASP.NET MVC 5.x):
- It has AutoValidateAntiforgeryTokenAttribute class that automates anti forgery validation for all POST, PUT, PATCH and DELETE actions.
- It has ValidateAntiForgeryToken and IgnoreAntiforgeryToken attributes to control token validation.
- Automatically adds anti forgery security token to HTML forms if you don't explicitly disable it. So, no need to call @Html.AntiForgeryToken() in most cases.
- It can read request token from HTTP header and the form field.
ASP.NET核心的MVC具有更好的防伪机制相比以前的版本(ASP.NET MVC 5。x):
它有autovalidateantiforgerytokenattribute类自动化的所有帖子,防伪验证,补丁和删除操作。
它有validateantiforgerytoken和IgnoreAntiforgeryToken属性控制令牌验证。
如果没有显式禁用,则自动向HTML表单添加防伪安全令牌。所以,不需要打”在大多数情况下,antiforgerytoken() HTML。
它可以从HTTP头和表单字段读取请求令牌。
ABP adds the following features:
- Automatically adds anti forgery token to the header for all AJAX requests.
- Provides abp.security.antiForgery.getToken() function to get the token in the javascript, even you will not need it much.
-
ABP增加了以下功能:
为所有Ajax请求自动添加反令牌到报头。
提供ABP。安全。防伪。gettoken()函数在JavaScript得到令牌,即使你不需要它。
Integration
Startup templates already integrated to CSRF protection out of the box. If you need to manually add it to your project (maybe you created your project before we added it), follow this guide.
启动模板已综合CSRF保护开箱。如果需要手动将其添加到项目中(可能在添加项目之前创建了项目),请遵循本指南。
Startup Class
First, we should add AutoValidateAntiforgeryTokenAttribute to global filters while adding MVC in ConfigureServices of Startup class:
services.AddMvc(options => { options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); });
Thus, all MVC actions (except GET, HEAD, OPTIONS and TRACE as declared before) will be automatically validated for anti forgery token.
Layout View
We should add the following code in our Layout view:
@using Abp.Web.Security.AntiForgery @inject IAbpAntiForgeryManager AbpAntiForgeryManager @{ AbpAntiForgeryManager.SetCookie(Context); }
Thus, all pages use this layout will include it. It creates and sets appropriate token cookies and makes javascript side working. If you have more than one layout, add this to all of them.
That's all we should do for ASP.NET Core MVC applications. All AJAX requests will work automatically. For non-ajax form submits, ASP.NET Core automatically adds anti forgery token field if you use one of asp-* tags in your form. So, no need to use @Html.AntiForgeryToken() normally.
因此,所有使用此布局的页面都将包含它。它创建并设置适当的令牌cookie并使JavaScript侧工作。如果您有不止一个布局,请将其添加到所有这些布局中。
这是我们应该做的是ASP.NET核心的MVC应用程序。所有Ajax请求都将自动工作。非Ajax表单提交,ASP.NET核心自动添加防伪标记领域,如果你使用一个ASP *标签在表单。因此,没有必要使用“HTML antiforgerytoken()正常。
Client Libraries(客户端库)
Anti forgery token should be provided in the request header for all AJAX requests, as we declared before. We will see how it's done here.
如我们前面声明的那样,在请求标头中为所有Ajax请求提供反伪造令牌。我们来看看它是怎么做的。
jQuery
abp.jquery.js defines an AJAX interceptor which adds the anti forgery token to the request header for every request. It gets the token from abp.security.antiForgery.getToken() javascript function.
abp.jquery.js定义为每个请求的请求标头添加防伪标记一个Ajax拦截。它从总部得到令牌。安全。防伪gettoken() JavaScript函数。
Angular
Angular automatically adds the anti forgery token to all AJAX requests. See Cross Site Request Forgery (XSRF) Protection section in Angularjs $http document. ABP uses the same cookie and header names as default. So, Angular integration works out of the box.
Angular自动添加反令牌令牌到所有Ajax请求。看到跨站请求伪造(XSRF)在AngularJS $HTTP文档保护部分。ABP使用相同的cookie和头名称作为默认值。这样,Angular集成可以使用了。
Other Libraries
If you are using any other library for AJAX requests, you have three options:
Intercept XMLHttpRequest(拦截XMLHttpRequest)
Since all libraries use the javascript's native AJAX object, XMLHttpRequest, you can define such a simple interceptor to add token to the header:
因为所有的库都使用JavaScript的原生Ajax对象,XMLHttpRequest,你可以定义这样一个简单的拦截添加令牌的头:
(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(使用库的拦截)
A good library provide interception points (like jquery and angularjs). So, follow your vendor's documentation to learn how to intercept requests and manipulate headers.
一个好的库提供拦截点(如jQuery和AngularJS)。因此,遵循您的供应商的文档来学习如何拦截请求和处理头文件。
Add the Header Manually(手动添加Header)
The last option, you can use abp.security.antiForgery.getToken() to get the token and add to the request header manually for every request. But you probably do not need this and solve the problem as descibed above.
最后一个选项,你可以使用ABP。安全。防伪。gettoken()获得令牌和添加手动为每个请求的请求头。但你可能不需要这个和上面解决问题了。
Internals(内部)
You may wonder how ABP handles it. Actually, we are using the same mechanism described in the angularjs documentation mentioned before. ABP stores the token into a cookie (as described above) and sets requests headers using that cookie. It also well integrates to ASP.NET MVC, Web API and Core frameworks for validating it.
你可能想知道ABP如何处理它。实际上,我们使用的是在AngularJS文档之前提到的描述相同的机制。ABP将令牌存储到cookie中(如上所述),并使用该cookie设置请求头。它还集成了ASP.NET的MVC,验证它的Web API和核心框架。