You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.Net C#自定义Action过滤器中验证同域请求(弃用易伪造的UrlReferer)

ASP.NET C# 自定义Action过滤器实现同域请求验证(无需UrlReferer)

实现思路

UrlReferer字段易被伪造且浏览器可能不发送,因此采用Origin请求头+Cookie验证的组合方案:

  • 跨域请求时浏览器会强制发送Origin头,且无法通过前端篡改,可直接验证是否匹配当前域名
  • 同域简单请求(如GET/HEAD)可能不带Origin,此时通过检查当前站点的Cookie(浏览器仅会自动携带同域Cookie)辅助验证

自定义过滤器实现

创建继承自ActionFilterAttribute的过滤器类,重写OnActionExecuting方法实现验证逻辑:

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Http;
using System;
using Microsoft.Extensions.Configuration;

public class SameDomainValidationFilter : ActionFilterAttribute
{
    private readonly string[] _allowedDomains;

    // 从配置读取允许的域名,支持多域名(用逗号分隔)
    public SameDomainValidationFilter(IConfiguration configuration)
    {
        var domains = configuration["AllowedDomains"];
        if (string.IsNullOrEmpty(domains))
            throw new InvalidOperationException("请在配置文件中设置AllowedDomains项");
        
        _allowedDomains = domains.Split(',', StringSplitOptions.RemoveEmptyEntries);
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var request = context.HttpContext.Request;
        var origin = request.Headers["Origin"].ToString();

        // 验证Origin头(存在时)
        if (!string.IsNullOrEmpty(origin))
        {
            var isAllowed = Array.Exists(_allowedDomains, domain => 
                origin.Equals(domain.Trim(), StringComparison.OrdinalIgnoreCase));
            
            if (!isAllowed)
            {
                context.Result = new Microsoft.AspNetCore.Mvc.ForbidResult("请求来源不合法");
                return;
            }
        }
        else
        {
            // 无Origin时,验证是否携带同域Cookie(示例用Identity认证Cookie,可替换为自定义Cookie)
            var hasValidCookie = request.Cookies.ContainsKey(".AspNetCore.Identity.Application");
            if (!hasValidCookie)
            {
                context.Result = new Microsoft.AspNetCore.Mvc.ForbidResult("请求来源验证失败");
                return;
            }
        }

        base.OnActionExecuting(context);
    }
}

配置与使用

1. 配置允许的域名

在appsettings.json中添加允许的域名(支持多个,逗号分隔):

{
  "AllowedDomains": "https://yourdomain.com,https://sub.yourdomain.com,https://localhost:5001"
}

2. 注册过滤器

全局注册(对所有API控制器生效)

在Program.cs中添加:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<SameDomainValidationFilter>();
});
局部注册(仅对特定控制器/Action生效)

直接在目标控制器或Action上标记:

[ApiController]
[Route("api/[controller]")]
[ServiceFilter(typeof(SameDomainValidationFilter))]
public class YourApiController : ControllerBase
{
    [HttpGet]
    public IActionResult GetData()
    {
        return Ok("请求验证通过");
    }
}

注意事项

  • 若需支持子域名通配(如*.yourdomain.com),可修改Origin验证逻辑,用origin.EndsWith(".yourdomain.com")替代精确匹配
  • 本地开发时记得将https://localhost:端口加入AllowedDomains,避免被拦截
  • Cookie验证可根据业务调整:若无需登录态,可自定义一个同域Cookie(前端页面加载时设置),后端验证该Cookie是否存在

内容的提问来源于stack exchange,提问作者Hassnain Balghari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 07:31:20