【问题标题】:Resolving route segment in asp net core mvc解析asp net core mvc中的路由段
【发布时间】:2017-04-06 14:07:33
【问题描述】:

我想在自定义属性中进行安全验证。一个很好的例子是,如果用户发出 GET 请求以检索具有给定 id 的实体,我想在属性中拦截该请求,将其交给操作过滤器,然后确定用户是否有权访问它。我唯一的问题是如何检索实体 ID。我不能在属性声明中传递它,因为它会被初始化一次而不是每个请求。相反,我想给我的自定义属性一个 url 模式,就像你给 HttpGet 或 HttpPost 一样,并让它根据上下文的 url 参数解析以产生一个实体 id。

这是我的属性:

public class RequireProjectAccessAttribute : TypeFilterAttribute
{
    public string UrlPattern { get; set; }
    public RequireProjectAccessAttribute(string urlPattern) : base(typeof(RequireProjectAccessFilter))
    {
        UrlPattern = urlPattern;
        Arguments = new object[] { urlPattern };
    }

    private class RequireProjectAccessFilter : IAsyncActionFilter
    {
        private readonly ICurrentSession _currentSession;
        private readonly string _urlPattern;

        public RequireProjectAccessFilter(ICurrentSession currentSession, string urlPattern)
        {
            _currentSession = currentSession;
            _urlPattern = urlPattern;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var projectId = /* some magic to resolve _urlPattern against the current url parameter values */
            if (/* user doesn't have access to project */)
            {
                context.Result = new UnauthorizedResult();
            }
            else
            {
                await next();
            }
        }
    }
}

这是我想使用它的方式:

[Route("api/[controller]")]
public class ProjectsController : BaseController
{

    public ProjectsController()
    {
    }

    [RequireProjectAccess("{projectId}")]
    [HttpGet("{projectId}")]
    public JsonResult GetById(int projectId)
    {
        /* retrieve project */
    }
}

【问题讨论】:

  • https://channel9.msdn。 com /Blogs/Seth-Juarez/Advanced-aspNET-Core-Authorization-with-Barry-Dorrans |转到此视频并跳到大约 30 分钟。

标签: c# asp.net asp.net-mvc asp.net-core asp.net-mvc-routing


【解决方案1】:

您只需要提供应该包含该值的路由键,然后在HttpContext 对象上使用扩展方法GetRouteValue(string key)

var projectId = context.HttpContext.GetRouteValue(_routeKey)?.ToString();

这意味着您的属性将如下所示:

public class RequireProjectAccessAttribute : TypeFilterAttribute
{
    public string RouteKey { get; set; }
    public RequireProjectAccessAttribute(string routeKey) : base(typeof(RequireProjectAccessFilter))
    {
        RouteKey = routeKey;
        Arguments = new object[] { routeKey };
    }

    private class RequireProjectAccessFilter : IAsyncActionFilter
    {
        private readonly ICurrentSession _currentSession;
        private readonly string _routeKey;

        public RequireProjectAccessFilter(ICurrentSession currentSession, string routeKey)
        {
            _currentSession = currentSession;
            _routeKey = routeKey;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var projectId = context.HttpContext.GetRouteValue(_routeKey)?.ToString();
            if (/* user doesn't have access to project */)
            {
                context.Result = new UnauthorizedResult();
            }
            else
            {
                await next();
            }
        }
    }
}

并用作这个(注意我只是传递了路由键的名称):

[RequireProjectAccess("projectId")]
[HttpGet("{projectId}")]
public JsonResult GetById(int projectId)
{
    /* retrieve project */
}

【讨论】:

  • 这很接近,但我想以与 HttpGet 解析其参数的方式完全相同的方式解析传递给 RequireProjectAccess 的内容。我不想传递“projectId”,我想传递“{projectId}”并让 MVC 使用其内部路由解析器使用正确的 URL 参数来解析它。
  • 我想我遗漏了一些东西。既然 "{projectId}" 已经被 Routing 解析了,并且在 RouteData 中可以使用 projectId 参数,为什么还需要再次解析呢?
猜你喜欢
  • 1970-01-01
  • 2021-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-04
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多