如何限制ASP.NET Web API仅允许所属Web应用访问
针对你的需求,这里有几种可行的方案,你可以根据实际场景选择或组合使用,来限制API仅允许来自abc.com网站的请求:
方法1:验证HTTP Referer请求头
浏览器发起的同站请求会携带Referer头,记录请求的来源页面域名。你可以在API中验证这个头是否来自abc.com,作为基础拦截手段。
实现代码(ASP.NET Action过滤器)
public class ValidateRefererAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var referer = filterContext.HttpContext.Request.UrlReferrer; // 检查Referer是否存在且域名是abc.com if (referer == null || !referer.Host.Equals("abc.com", StringComparison.OrdinalIgnoreCase)) { filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden, "请求来源无效"); return; } base.OnActionExecuting(filterContext); } }
使用时,在API控制器或具体Action上添加标记:
[ValidateReferer] public class YourApiController : ApiController { // API接口方法 }
注意:
Referer头可以被伪造,也可能在某些隐私场景下被浏览器屏蔽,因此仅作为第一道防线,建议结合其他方法使用。
方法2:使用Anti-Forgery Token(适合AJAX/表单请求)
ASP.NET的Anti-Forgery Token机制可以确保请求仅来自本站生成的页面,有效阻止外部工具的直接调用。
步骤1:在网站页面生成Token
@* 网站的Razor页面或视图中添加 *@ @Html.AntiForgeryToken()
步骤2:AJAX请求携带Token
$.ajax({ url: '/api/your-endpoint', type: 'POST', headers: { // 携带页面生成的Token 'RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val() }, data: { /* 请求数据 */ }, success: function(res) { // 处理响应 } });
步骤3:API验证Token
在API的Action上添加验证属性:
[HttpPost] [ValidateAntiForgeryToken] public IHttpActionResult YourEndpoint(YourRequestModel model) { // 处理请求逻辑 return Ok(); }
说明:该方法对GET请求支持有限(GET请求通常不携带表单Token),如果API有GET接口,建议改为POST,或结合其他验证方式。
方法3:IIS URL重写规则拦截(无需改代码)
直接在IIS层面配置规则,拦截非abc.com来源的API请求。
配置步骤
- 打开IIS管理器,找到你的API虚拟应用,打开「URL重写」模块。
- 添加入站规则:
- 规则名称:
Block External API Access - 匹配URL:
^api/.*(根据你的API实际路径调整) - 条件:添加条件,输入
{HTTP_REFERER},匹配类型选择「与模式不匹配」,模式为https?://abc.com/.* - 操作:选择「自定义响应」,状态代码设为
403,描述填Forbidden
- 规则名称:
- 保存规则即可生效。
注意:同样依赖
Referer头,适合作为辅助拦截手段。
方法4:共享密钥验证(更高安全性)
在网站和API之间约定一个共享密钥,网站发起请求时在请求头中携带密钥,API验证密钥合法性。
步骤1:网站请求携带密钥
$.ajax({ url: '/api/your-endpoint', type: 'POST', headers: { 'X-Site-Api-Key': 'your-secure-shared-key' // 建议从配置文件读取,不要硬编码 }, data: { /* 请求数据 */ }, success: function(res) { // 处理响应 } });
步骤2:API验证密钥
编写Action过滤器验证密钥:
public class ValidateSiteApiKeyAttribute : ActionFilterAttribute { private const string ApiKeyHeader = "X-Site-Api-Key"; // 建议从Web.config或配置中心读取,避免硬编码 private const string ValidKey = "your-secure-shared-key"; public override void OnActionExecuting(ActionExecutingContext filterContext) { if (!filterContext.HttpContext.Request.Headers.TryGetValue(ApiKeyHeader, out var receivedKey) || !receivedKey.Equals(ValidKey, StringComparison.Ordinal)) { filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden, "密钥无效"); return; } base.OnActionExecuting(filterContext); } }
在API控制器上标记使用:
[ValidateSiteApiKey] public class YourApiController : ApiController { // API接口方法 }
说明:如果是前端AJAX请求,密钥可能被开发者工具看到,建议结合Anti-Forgery Token一起使用;如果是网站服务器端调用API,这个方法安全性很高。
方法5:验证会话上下文(适合登录场景)
如果你的网站需要用户登录,且API和网站共享会话(同站点虚拟应用默认共享会话),可以检查API请求是否携带有效的用户会话。
实现代码
public class ValidateUserSessionAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var session = filterContext.HttpContext.Session; // 假设网站登录后会将用户ID存入Session if (session == null || session["LoggedInUserId"] == null) { filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized, "无有效会话"); return; } base.OnActionExecuting(filterContext); } }
在API控制器上添加标记即可。
推荐方案组合
为了最大化安全性,建议组合使用多种方法,比如:
Anti-Forgery Token+共享密钥验证:适合前端AJAX调用API的场景Referer检查+IIS重写规则+会话验证:适合需要用户登录的网站场景
内容的提问来源于stack exchange,提问作者MR K

