Отправка параметров метода в фильтр действий через конструктор - PullRequest
0 голосов
/ 26 января 2019

Я создаю веб-сайт в ASP.NET Core, и я только начал настраивать некоторые фильтры для управления доступом к определенным методам, и одним из критериев для некоторых методов является заголовок запроса Referer.

Я хотел бы отправить действительный URL-адрес для Referer в фильтр действий в качестве аргумента через конструктор.

Я создал следующий фильтр:

public class RefererFilter : ActionFilterAttribute
{
    private List<string> referers;

    public RefererFilter(params string[] _referers)
    {
        referers = new List<string>(_referers);
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        bool valid = false;

        foreach (string referer in referers)
        {
            if (context.HttpContext.Request.Headers["Referer"].ToString() == ("https://" + context.HttpContext.Request.Host.Value + referer))
            {
                valid = true;
                break;
            }
        }

        if (!valid)
            context.Result = new StatusCodeResult(403);

        base.OnActionExecuting(context);
    }
}

И я быхотел бы использовать это так:

[RefererFilter("/Users/ChangePassword/" + id)]
public IActionResult PasswordChanged(int id)
{
    return View();
}

Проблема в том, что переменная "id" не существует в вызове фильтра.

Я знаю, что есть другие способы сделать это:получение атрибутов из фильтра действий, зная их имя в методе, но это заставило бы меня создавать различные фильтры, потому что URL не все имеют одинаковую структуру.

Есть ли способ, которым это можно сделать

1 Ответ

0 голосов
/ 26 января 2019

Тогда просто дайте фильтру знать имя параметра действия.Это единственное, что нужно знать фильтру.

Заметили ли вы, что HttpGetAttribute также делает это, передавая имя параметра

        [HttpGet("{id}")]
        public string Get(int id)
        {

И помните, что фигурные скобки недопустимы вURI (см. RFC 3986).Вот почему мы можем использовать его как символ, который будет заменен позже значением параметра действия.Таким образом, вы можете сделать так, чтобы шаблон URL стал таким,

    [RefererFilter("/Users/ChangePassword/{id}")]
    public IActionResult PasswordChanged(int id)
    {
        return View();
    }

    [RefererFilter("/Users/EditUser/{id}/UserEmail/{email}")]
    public IActionResult EditUser(int id, string email)
    {
        return View();
    }

Тогда в RefererFilter вам нужно будет проанализировать значение параметра action в методе OnActionExecuting, например,

    public class RefererFilter : ActionFilterAttribute
    {
        private List<string> referers;

        public RefererFilter(params string[] _referers)
        {
            referers = new List<string>(_referers);
        }

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            bool valid = false;

            foreach (string referer in referers)
            {
                string r = referer;
                foreach(var arg in context.ActionArguments)
                {
                    r = r.Replace($"{{{arg.Key}}}", arg.Value.ToString());
                }

                if (context.HttpContext.Request.Headers["Referer"].ToString() == $"https://{context.HttpContext.Request.Host.Value}{r}")
                {
                    valid = true;
                    break;
                }
            }

            if (!valid)
                context.Result = new StatusCodeResult(403);

            base.OnActionExecuting(context);
        }
    }
...