.NET注册端点安全防护:如何仅允许自有网站前端访问
保护未认证注册端点的实践方案
针对你开发.NET应用时遇到的未认证注册端点防滥用问题,以下是结合.NET生态的可行防护策略:
一、推荐实践与.NET专属特性
1. 集成人机验证(核心防护)
使用Google reCAPTCHA v3或hCaptcha这类无感知验证服务,.NET中可通过官方NuGet包快速集成。这类验证会分析用户的浏览器行为(如鼠标移动、页面停留时间)生成风险评分,Postman等工具无法模拟真实用户的浏览器行为,会被判定为高风险请求直接拦截。
2. 会话绑定的CSRF防护优化
ASP.NET Core的AntiForgery中间件不仅支持已认证用户,也能为未认证用户创建临时会话:
- 配置中间件时,将CSRF令牌与用户的User-Agent、客户端IP的哈希值绑定,验证令牌时同时校验这些信息。
- 示例代码片段:
services.AddAntiforgery(options => { options.Cookie.Name = "X-CSRF-Token"; options.FormFieldName = "__RequestVerificationToken"; options.AdditionalDataProvider = new CustomAntiForgeryDataProvider(); }); public class CustomAntiForgeryDataProvider : IAntiforgeryAdditionalDataProvider { public string GetAdditionalData(HttpContext context) { // 生成UA和IP的哈希值作为额外验证数据 var userAgent = context.Request.Headers["User-Agent"].ToString(); var ip = context.Connection.RemoteIpAddress?.ToString() ?? ""; return HashHelper.ComputeSha256($"{userAgent}:{ip}"); } public bool ValidateAdditionalData(HttpContext context, string additionalData) { var currentData = GetAdditionalData(context); return string.Equals(currentData, additionalData, StringComparison.Ordinal); } }
就算攻击者从前端获取了CSRF令牌,换用Postman调用时,UA或IP不一致,验证会直接失败。
3. 请求频率限制
利用ASP.NET Core 7+内置的Rate Limiting中间件,按IP地址或临时会话ID限制请求次数:
services.AddRateLimiter(options => { options.RejectionStatusCode = StatusCodes.Status429TooManyRequests; options.AddFixedWindowLimiter("register-limit", opt => { opt.Window = TimeSpan.FromMinutes(15); opt.PermitLimit = 3; // 15分钟内最多3次注册请求 opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; opt.QueueLimit = 0; }); });
在注册端点上应用限制:
[EnableRateLimiting("register-limit")] [HttpPost("register")] public async Task<IActionResult> Register([FromBody] RegisterModel model) { // 注册逻辑 }
4. 动态/隐藏端点路径
避免使用/api/register这类直白的路径,改为动态生成的路径(如/api/register-xyz123),前端通过服务器渲染页面时获取该路径。攻击者即使抓包到某次请求的路径,下次部署后路径变更就会失效。
5. Referer/Origin头验证
在中间件中检查请求的Referer或Origin头,仅允许来自自有域名的请求:
app.Use(async (context, next) => { if (context.Request.Path.StartsWithSegments("/api/register")) { var origin = context.Request.Headers["Origin"].FirstOrDefault(); var referer = context.Request.Headers["Referer"].FirstOrDefault(); var allowedDomains = new[] { "https://your-domain.com" }; if (!allowedDomains.Contains(origin) && !referer?.StartsWith("https://your-domain.com") == true) { context.Response.StatusCode = StatusCodes.Status403Forbidden; return; } } await next(); });
虽然该头可以被伪造,但作为第一道防线能拦截大部分非专业攻击。
二、关于无法被Postman伪造的验证方式
不存在绝对无法被伪造的验证方式,但组合多种防护措施可以将攻击成本提升到几乎不可行的程度:
- 人机验证+会话绑定CSRF+频率限制的组合,Postman无法同时模拟浏览器行为、匹配会话绑定的UA/IP、绕过频率限制。
- 例如reCAPTCHA v3的令牌会绑定用户的浏览器环境,Postman请求的令牌会被服务端判定为低信任度,直接拒绝。
三、通用场景(已认证/未认证接口防Postman调用)
- 未认证接口:采用上述的人机验证+频率限制+会话CSRF+头验证组合。
- 已认证接口:在常规JWT/OAuth2认证基础上,添加:
- 请求频率限制(按用户ID+IP);
- 可选的请求签名:前端用预共享密钥(需通过环境变量注入,避免硬编码)对请求参数+时间戳生成签名,后端验证签名有效性,Postman难以获取密钥并生成合法签名。
内容的提问来源于stack exchange,提问作者Damion Silver
相关产品推荐
相关产品推荐

