是否可以只覆盖一个授权过滤器?

时间:2015-05-21 17:25:42

标签: asp.net-mvc asp.net-mvc-5 asp.net-mvc-5.2

我遇到过多种授权过滤器强制执行不同条件的情况:

<UserLevelCanAccessThings>
<UserHasPaidForThings>
Partial Public Class ThingsController
    Inherits Controller

    Function EditThing() As ActionResult
        ...
        Return View()
    End Function

    <OverrideUserIsPaid>
    Function PayToUnlockThings() As ActionResult
        ...
        Return View()
    End Function

End Class

现在我遇到了一种情况,我需要一个操作绕过只有一个的过滤器。例如,如果您已达到足够高的级别(第一个过滤器)并且您已经为该访问付费(第二个过滤器),则假设您被允许访问此控制器以使用Things

Pay方法需要强制执行第一个条件而不是第二个条件,因为我不想阻止用户付款,因为当他尝试付款时他没有付款!

(我知道我可以在其他地方移动Pay方法,但在我的实际情况下,这是不可取的。这只是一个例子来说明我的要求。)

全局OverrideAuthorization属性会关闭所有授权,但我需要对此更具选择性。我怎么能这样做?

1 个答案:

答案 0 :(得分:0)

this answer Darin后,我这样做了:

Public Class OverrideUserIsPaidAttribute
    Inherits AuthorizeAttribute

    Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext)
        'no op
    End Sub
End Class

Public Class UserIsPaidAttribute
    Inherits AuthorizeAttribute

    Public Overrides Sub OnAuthorization(filterContext As AuthorizationContext)
        'get all other filters attached to this action, controller, or globally
        Dim otherFilters = filterContext.ActionDescriptor.GetCustomAttributes(True).AsEnumerable '.Where(Function(x) TypeOf x Is IAuthorizationFilter And Not TypeOf x Is OverridePlayerIsPaidAttribute).AsEnumerable(Of IAuthorizationFilter)()
        otherFilters = otherFilters.Union(filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(True))
        otherFilters = otherFilters.Union(GlobalFilters.Filters.Select(Function(x) x.Instance))

        'if any of them is an override, bail out before validating
        If otherFilters.OfType(Of UserIsPaidAttribute).Count > 0 Then Return

        'regular validation here
    End Sub

基本上,它增强了UserIsPaid授权,以检查操作,控制器和全局过滤器的属性,以查看是否指定了覆盖,如果是,则根本不执行自己的授权。这对我来说似乎很干净,但我愿意接受建议。