在 Asp.Net Core WebAPI 中防御跨站请求伪造攻击
在 Asp.Net Core WebAPI 中防御跨站请求伪造攻击
什么是跨站请求伪造
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。[1] 跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
使用 Asp.Net Core 内置的 Antiforgery
Asp.Net Core 应用中内置了 Microsoft.AspNetCore.Antiforgery
包来支持跨站请求伪造。 如果你的应用引用了 Microsoft.AspNetCore.App
包, 则就已经包含了 Microsoft.AspNetCore.Antiforgery
。 如果没有, 则可以使用下面的命令来添加这个包:
dotnet add package Microsoft.AspNetCore.Antiforgery
添加了这个包之后, 需要先修改 Startup.cs
文件中的 ConfigureServices
方法, 添加下面的配置:
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services.AddAntiforgery(options => {
options.Cookie.SameSite = SameSiteMode.Lax;
// 客户端要向服务端发送的 Header 的名称, 用于 XSRF 验证;
options.HeaderName = "X-XSRF-TOKEN";
});
}
}
在 SecurityController.cs
文件中添加一个 Api , 来颁发凭据:
[Route("api/[controller]")]
[ApiController]
public class SecurityController : Controller {
private IAntiforgery antiforgery;
public SecurityController(
IAntiforgery antiforgery
) {
this.antiforgery = antiforgery;
}
[HttpGet("xsrf-token")]
public ActionResult GetXsrfToken() {
var tokens = antiforgery.GetAndStoreTokens(HttpContext);
// 向客户端发送名称为 XSRF-TOKEN 的 Cookie , 客户端必须将这个 Cookie 的值
// 以 X-XSRF-TOKEN 为名称的 Header 再发送回服务端, 才能完成 XSRF 认证。
Response.Cookies.Append(
"XSRF-TOKEN",
tokens.RequestToken,
new CookieOptions {
HttpOnly = false,
Path = "/",
IsEssential = true,
SameSite = SameSiteMode.Lax
}
);
return Ok();
}
}
当客户端请求 ~/api/security/xsrf-token
时, 服务端发送两个 Cookie :
- .AspNetCore.Antiforgery.xxxxxx 一个 HTTP Only 的 Cookie , 用于服务端验证;
- XSRF-TOKEN 客户端需要将这个 Cookie 的值用 X-XSRF-TOKEN 的 Header 发送回服务端, 进行验证;
注意: 这两个 Cookie 不支持跨域请求, 只能在相同的站点内请求, 也是出于安全性方面的考虑。
可以为某一个 ApiController 或者 Action 方法单独添加 ValidateAntiForgeryTokenAttribute
标记来验证 XSRF-TOKEN
, 也可以全局注册一个 AutoValidateAntiforgeryTokenAttribute
过滤器来进行自动验证, 代码如下:
public class Startup {
public void ConfigureServices(
IServiceCollection services,
IHostingEnvironment env
) {
services.AddMvc(options => {
// 在生产环境中添加自动 XSRF 验证
if (env.IsProduction()) {
options.Filters.Add(
new AutoValidateAntiforgeryTokenAttribute()
);
}
});
}
}
注意问题: 不是所有的方法都需要进行 XSRF 认证,除了 GET, HEAD, OPTIONS 和 TRACE 之外的方法才支持 XSRF 认证。
Angular 内置支持
Angular 的 Http 模块内置支持 XSRF , 前提条件如下:
- 存在客户端可以操作的名称为 XSRF-TOKEN 的 Cookie ;
- 该 Cookie 不能是 HttpOnly 的, 否则客户端脚本无法读取;
- 该 Cookie 的 Path 必须为
/
;
这三个条件都满足, 则在向服务端请求时自动发送名称为 X-XSRF-TOKEN
的 Header , 值则为 XSRF-TOKEN 的 Cookie 的值, 这样就回自动满足上面的服务端的设置, 实现自动防御跨站请求伪造。
- 【jfinal修仙系列】扩展CacheInterceptor支持Redis缓存
- 基于Redis的定时任务
- 【jfinal】扩展JFIANL 支持加载jar包中SQL模板
- 【jfinal修仙系列】扩展ShiroCacheManager 支持Redis缓存
- 【springboot】 springboot 整合mybatis-plus
- jfinal-swagger让你的应用接口更加简单
- 【springboot】 spring session 分布式会话共享
- 基于jfinal Template的Shiro 标签
- 基于Spring Cloud 少量配置完成单点登录开发
- Spring 必知概念(一)
- 如何在EHAB(EntLib)中定义”细粒度”异常策略?
- MVC、MVP以及Model2[下篇]
- Dora.Interception: 一个为.NET Core度身定制的AOP框架
- 为了支持AOP的编程模式,我为.NET Core写了一个轻量级的Interception框架[开源]
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 比PS还好用!Python 20行代码批量抠图
- 将有序数组转化为二叉搜索树
- 至少有K个重复字符的最长子串
- django这些查询技巧你会了吗?
- 手把手教你配置vim,小白也可以
- 【NPM库】- 0x02
- 最长有效括号
- 统计全为1的子矩形
- Android Camera1中的人脸检测
- Executors功能如此强大,ThreadPoolExecutor功不可没(一)
- dotNET:怎样处理程序中的异常(实战篇)?
- 二维背包问题
- 小程序系列之禁用视频快进
- springBoot整合Mq报错:JmsMessagingTemplate that could not be found
- TCP:测试小工具TCPing