ASP.NET core 中的请求验证Razor Pages是一种旨在防止可能的跨站点请求伪造攻击的机制,也称为缩写词XSRF和CSRF。在CSRF攻击期间,恶意用户将使用经过身份验证的用户的凭据在网站上执行某些操作以使其受益。
用于说明此类攻击的规范示例涉及在线银行业务。当您在线登录银行帐户时,您的浏览器会收到一个身份验证cookie,然后在您每次提出请求时将其传递回银行网站,让您保持登录状态。身份验证cookie将具有预定的生命周期。它可能是基于会话的,这意味着它可以在您关闭网上银行的浏览器选项卡后的一段时间内有效,而不使用银行应用程序的注销功能而不关闭浏览器。
虽然此Cookie仍然有效,但您发现自己位于另一个网站上,该网站会向您的银行网站发送一个表单,从而将您的帐户转移到另一个网站。此表单帖子由您的cookie进行身份验证,银行站点对该事务进行认证,因为它无法验证请求的来源。
ASP.NET框架为此类攻击提供的预防机制涉及验证POST对Razor页面发出的任何请求是否源自同一站点上的表单。
这是通过__RequestVerificationToken在每个表单的末尾注入一个带有加密值的隐藏表单字段,并将相同的值传递给与表单请求一起发送的cookie来实现的。当ASP.NET Core处理POST请求时,将验证这两个项及其值的存在。如果验证失败,框架将返回HTTP状态代码400,表示错误请求。
我们有可以有4种选择,
一种是全局关闭防伪令牌验证, 对于多数网站来讲是不用验证输入的.
一种是全局关闭防伪令牌验证, 单个页面开启防伪令牌验证. (推荐,安全又轻松)
一种是全局开启防伪令牌验证, 每个ajax请求都增加 header信息.(最安全,银行和电商类网站推荐)
一种是全局开启防伪令牌验证,但是对于单个页面关闭防伪令牌验证,
全局开关防伪令牌验证。这可以通过以下ConfigureServices方法全局完成
在Startup.cs类的ConfigureServices方法进行配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(o => {
o.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute()); //忽略XSRF验证, 方便ajax请求,我们的服务一般都是没关系的, 对于需要安全验证的内容, 最好在页面上增加属性, 如果需要开启全局关闭防伪令牌验证, 请注释这行代码
});
}
对于需要安全验证的内容, 最好在页面上增加属性
[IgnoreAntiforgeryToken(Order = 1001)]
public class IndexModel : PageModel
{
public void OnPost()
{
}
}
ValidateAntiForgeryToken默认应用的属性的Order 为1000,因此该IgnoreAntiforgeryToken属性需要更高的Order 。
或者,您可以如上所述全局关闭令牌验证,然后通过使用ValidateAntiForgeryToken属性修饰相应的PageModel类(将相同的逻辑应用于Order以前的值),逐个选择性地应用令牌验证:
[ValidateAntiForgeryToken(Order = 1000)]
public class IndexModel : PageModel
{
public void OnPost()
{
}
}
该ValidateAntiForgeryToken属性在其名称中具有大写“F”,而IgnoreAntiforgeryToken具有小写“f”。这是设计的。
选择退出Antiforgery验证不会阻止隐藏字段或cookie的生成。它只是跳过验证过程。一般来说,没有充分的理由这样做。如果您希望站点接受来自外部域的POST请求,建议的解决方案是使用Web API控制器。
可以通过AntiforgeryOptions课程配置与AntiForgery功能相关的各种选项:
选项 | 描述 | 默认值 |
---|---|---|
Cookie | 提供对配置cookie方面的访问权限 | |
Cookie | 提供对配置cookie方面的访问权限 | |
FormFieldName | 用于隐藏表单字段的名称 | __RequestVerificationToken |
HeaderName | 用于请求标头的名称 | __RequestVerificationToken |
SuppressXFrameOptionsHeader | 如果设置为true,X-Frame-Options则不会设置标头。默认情况下,它使用值设置SAMEORIGIN ‘假’ |
您可以ConfigureServices在“启动” 中的方法中配置这些选项。以下示例将标题名称更改__RequestVerificationToken为XSRF-TOKEN:
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
AJAX发布请求和JSON
假设您没有选择禁用请求验证,如果您想通过AJAX发布JSON而不生成错误请求结果,则需要执行一些额外的步骤。AJAX POST请求不需要表单,但向页面添加空表单是生成防伪标记的最简单方法。然后,您需要将其值添加为请求标头,因为ASP.NET Core不会解析JSON以查找验证令牌。以下是使用jQuery $.ajax方法实现的方法:
var postSubmit = $.ajax({
type: "POST",
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
url: "/yourformhandler",
data: JSON.stringify({ ... }),
contentType: "application/json"
}).done(function(response){
//...
});