在AuthorizationFilter之前执行ASP.NET Core MVC ActionFilter

时间:2019-02-20 15:44:50

标签: c# asp.net-core asp.net-core-mvc action-filter

在我的网站上,我有一些controller仅限经过身份验证的用户使用。除此之外,还有一些控制器需要身份验证,还需要根据一年中的时间来限制ALSO。

为此,我创建了一个TimeRangeFilter ActionFilter / ResourceFilter

是这样的:

public class TimeRangeFilter : Attribute, IActionFilter, IOrderedFilter
{
  public string AllowedMonths { get; set; } // like |3|4|5|
  public string RedirectUrl { get; set; }
  ...... // OnActionExecuting....
}

然后,在我的Controller的{​​{1}}上,我这样实现:

class

但是,即使[TimeRangeFilter(AllowedMonths = "|3|4|", RedirectUrl = "/feature/welcome", Order = 1)] [Authorize] [IsNotNefarious] public class HubController : BaseController {...} 上有IOrderedFilter interfacefilter也会先执行,然后执行我的AuthorizationFilter

对于此欢迎页面,我不想要求用户登录才能看到它。但是我不想必须根据允许的月份来更改进入我的中心页面的URL。

如何在执行TimeRangeFilter之前优先执行ActionFilter / ResourceFilter并使其短路?

2 个答案:

答案 0 :(得分:2)

@Alexander提供的解决方案在.NET Core 3.1中不再起作用;现在Authorize中的AuthorizationMiddleware属性正在评估中,需要经过很多步骤才能过滤条件。

最好的新方法是自己制作自定义中间件,将其插入UseRouting();启动后,然后手动查询端点信息。示例:

public class TimeRangeAttribute : Attribute {
    public string Info { get; set; }
}

public class TimeRangeMiddleware {
    private readonly RequestDelegate _next;
    public TimeRangeMiddleware(RequestDelegate next) => _next = next;

    public async Task Invoke(HttpContext context) {
        var endpoint = context.GetEndpoint();
        if (endpoint?.Metadata.GetMetadata<TimeRangeAttribute>() != null) {
            // check allowed or not
        }
        if(_next != null) await _next(context);
    }
}

// In Startup
public void Configure(...) {
    // ....
    app.UseRouting();
    app.UseMiddleware<TimeRangeMiddleware>();
    app.UseAuthentication();
    app.UseAuthorization();
    // ...
}

答案 1 :(得分:1)

最简单的答案是“您不能使ActionFilterAuhtorizeFilter之前执行”。但是您可以将TimeRangeFilter设置为授权过滤器

public class TimeRangeFilterAttribute : Attribute, IAuthorizationFilter, IOrderedFilter
{
    public string AllowedMonths { get; set; } // like |3|4|5|
    public string RedirectUrl { get; set; }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (not allowed) {
            context.Result = new RedirectResult(RedirectUrl);
        }
    }
}

指定Order = 0使其在其他Authorize检查之前运行,或者尝试对其实施IOrderedFilter,它也会首先执行。 / p>