aspnet访可
ASP.NET 防跨站请求伪造(CSRF)攻击是构建安全Web应用的核心防线,其核心机制是通过验证令牌(Anti-Forgery Token)确保提交到服务器的请求确实源自用户有意操作的应用页面,而非恶意第三方伪造。

ASP.NET Core 中的 CSRF 防护机制
ASP.NET Core 内置了强大且灵活的 CSRF 防护(常称为 XSRF 防护),主要通过 ValidateAntiForgeryToken 和自动化的令牌生成与验证实现。
-
令牌生成与嵌入:
- 在 Razor 视图(
.cshtml)中,使用@Html.AntiForgeryToken()或<form>标签上的asp-antiforgery="true"(通常默认启用)会在表单内生成一个隐藏字段(__RequestVerificationToken)。 - 框架会设置一个包含相同令牌值的加密 Cookie(默认名称为
.AspNetCore.Antiforgery.<...>)。 - 对于 AJAX 请求,通常需要从 Cookie 或表单中读取令牌值,并将其作为请求头(通常是
RequestVerificationToken)发送,JavaScript 可以访问@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery antiforgery并通过antiforgery.GetAndStoreTokens(HttpContext)获取令牌值。
- 在 Razor 视图(
-
令牌验证:
- 控制器/Action 级别验证: 在需要保护的 Controller Action 方法上添加
[ValidateAntiForgeryToken]特性,此特性会检查:- 请求是否包含有效的
__RequestVerificationToken表单字段值。 - 请求是否包含有效的
RequestVerificationToken请求头值。 - 上述令牌值是否与请求携带的 Anti-Forgery Cookie 中的值匹配(采用“双提交Cookie”模式)。
- 请求是否包含有效的
- 全局验证: 在
Program.cs中配置 Anti-Forgery 选项为全局生效(需谨慎评估需求):builder.Services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN"); // 可选:自定义Header名 ... app.UseAntiforgery(); // 这将尝试验证所有非安全(如POST, PUT, DELETE)方法的请求
- 控制器/Action 级别验证: 在需要保护的 Controller Action 方法上添加
ASP.NET Web Forms (传统 ASP.NET) 中的机制
在传统 ASP.NET 中,核心机制是 ViewStateUserKey 和 @Html.AntiForgeryToken() (MVC)。

- ViewStateUserKey (Web Forms 核心防御):
- 在
Page_Init中设置Page.ViewStateUserKey = Session.SessionID;(或唯一用户标识)。 - 原理:将当前用户的会话 ID(或唯一标识)编码到页面的 ViewState 中,服务器在回发时验证 ViewState 中的用户标识是否与当前用户会话匹配,攻击者无法伪造包含受害者有效标识的 ViewState。
- 在
- AntiForgeryToken (MVC):
- 用法与 ASP.NET Core MVC 类似:在视图中使用
@Html.AntiForgeryToken(),在 Action 上使用[ValidateAntiForgeryToken]。 - 同样依赖隐藏表单字段和 Cookie 进行令牌匹配验证。
- 用法与 ASP.NET Core MVC 类似:在视图中使用
专业级防护策略与最佳实践
-
严格遵循最小权限原则:
-
即使通过 CSRF 防护,也要确保后端 Action 在执行关键操作(如转账、修改密码、删除数据)前,验证当前登录用户确实拥有执行该操作的权限,CSRF 防护阻止了请求伪造,但不能替代业务逻辑权限检查。
-
示例:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteProduct(int productId) { var product = await _context.Products.FindAsync(productId); if (product == null) return NotFound(); // 核心权限验证:确保当前用户有权删除这个特定产品 if (!await _productService.UserCanDeleteProduct(User.Identity.Name, productId)) { return Forbid(); // 或返回其他错误 } _context.Products.Remove(product); await _context.SaveChangesAsync(); return RedirectToAction("Index"); }
-
-
正确配置 Cookie 安全属性:
- Anti-Forgery Cookie 必须 标记为
Secure(仅 HTTPS 传输)、HttpOnly(防止 JavaScript 窃取,虽然令牌本身通常需要 JS 读取用于 AJAX)、SameSite。 - SameSite 策略:
SameSite=Strict或Lax(现代浏览器默认 Lax) 能有效防御大多数 CSRF 攻击,阻止第三方网站发送 Cookie。- 在
Program.cs(Core) 或Global.asax/Web.config(Web Forms) 中配置:// ASP.NET Core Program.cs builder.Services.AddAntiforgery(options => { options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 强制 Secure options.Cookie.HttpOnly = true; // 推荐 options.Cookie.SameSite = SameSiteMode.Strict; // 或 Lax, 根据跨站需求调整 });
- Anti-Forgery Cookie 必须 标记为
-
API 与 SPA 的防护特殊性:

- 挑战: API 通常是无状态的,依赖 Token (如 JWT) 认证,不依赖 Cookie,传统的 Cookie+表单域/Header 验证模式可能不直接适用,SPA 应用大量使用 AJAX。
- 解决方案:
- 继续使用 Anti-Forgery Token: SPA 应用在加载时,可以从一个受 CSRF 保护的端点(通常是加载首页或专门的令牌获取端点)获取 Anti-Forgery Token(通常通过 Cookie 发送,并由 JS 读取存储),然后在后续的 AJAX 请求(特别是非 GET 请求)中,将此 Token 作为自定义 Header (如
X-CSRF-TOKEN) 发送,后端 API 配置验证该 Header 与 Cookie 中的令牌是否匹配,ASP.NET Core 内置支持此模式。 - 利用认证 Token 本身: 对于使用 Bearer Token (如 JWT) 的 API,由于其通常不自动随请求发送(需要前端显式设置 Authorization Header),攻击者无法在伪造的请求中携带受害者的有效 Token,CSRF 风险较低。但这不能完全替代防御! 如果用户的认证 Token 以不安全方式存储(如 localStorage 且存在 XSS 漏洞),攻击者可能窃取 Token 并发起伪造请求,确保:
- Token 安全存储(考虑使用
httpOnly、Secure、SameSite的 Cookie,或确保 localStorage/sessionStorage 无 XSS 风险)。 - 设置较短的 Token 有效期。
- 关键操作仍需二次确认: 对于极高权限操作,强制要求用户在应用内进行二次验证(如重新输入密码、使用 MFA)。
- Token 安全存储(考虑使用
- 自定义 Header 检查: 要求 AJAX 请求设置一个自定义 Header (如
X-Requested-With: XMLHttpRequest),并在后端检查其存在,因为浏览器同源策略限制,攻击者通常无法在跨域请求中设置自定义 Header,这是防御“简单”CSRF 的有效补充,但不能单独依赖,因为旧浏览器或某些代理可能允许修改 Header。
- 继续使用 Anti-Forgery Token: SPA 应用在加载时,可以从一个受 CSRF 保护的端点(通常是加载首页或专门的令牌获取端点)获取 Anti-Forgery Token(通常通过 Cookie 发送,并由 JS 读取存储),然后在后续的 AJAX 请求(特别是非 GET 请求)中,将此 Token 作为自定义 Header (如
-
区分 GET 与 非 GET 请求:
- 核心原则: 永远不要使用 GET 请求执行状态修改操作! GET 请求应设计为幂等的、安全的(仅查询),遵循 RESTful 语义(使用 POST, PUT, PATCH, DELETE)。
- 原因: GET 请求容易被伪造(如
<img src="https://bank.com/transfer?to=attacker&amount=1000">),虽然[ValidateAntiForgeryToken]通常只应用于非 GET 方法,但确保逻辑本身不被 GET 访问是第一道防线,在 ASP.NET Core 的全局验证 (app.UseAntiforgery()) 中,默认也只验证非安全方法。
-
防御点击劫持:
- 点击劫持是 CSRF 的“近亲”,攻击者使用 iframe 覆盖诱导用户点击看似无害的按钮,实际触发恶意操作。
- 防御: 使用 HTTP 响应头
X-Frame-Options(推荐DENY或SAMEORIGIN) 或现代浏览器支持的Content-Security-Policy(CSP) 中的frame-ancestors指令来阻止页面被嵌入到 iframe 中。// ASP.NET Core Middleware or Action Filter context.Response.Headers.Append("X-Frame-Options", "DENY"); // 或更强大的 CSP context.Response.Headers.Append("Content-Security-Policy", "frame-ancestors 'none';");
ASP.NET 提供了坚实的 CSRF 防护基础(Anti-Forgery Tokens, ViewStateUserKey),构建真正安全的 Web 应用需要在正确配置和使用这些内置机制的基础上,结合严格的权限校验、安全的 Cookie/Token 策略、对 API/SPA 场景的特殊处理、遵循安全的 HTTP 方法规范以及防御点击劫持,将 CSRF 防护视为纵深防御体系中不可或缺的一环,而非唯一的安全措施。
您在项目中如何平衡便捷性与高安全等级操作的防护强度?对于涉及文件上传或包含复杂参数的API端点,是否有更精细的CSRF验证策略或审计日志方案?
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/18924.html