c# - 相互了解的多个授权属性

标签 c# asp.net-mvc asp.net-mvc-4 authorize-attribute

我有一个非常简单的场景。我想用自定义授权属性装饰我的 Controller /操作。如果任何 属性有效,则应授予授权。例如,

[MyAuth(1)]
[MyAuth(2)]
public class MyController : Controller
{
    ...
}

我无法将这些参数组合成一个授权属性。上面的例子只是一个简化的例子。

如果任一属性授权用户,我希望用户获得授权。我假设 ActionFilterAttributeAuthorizeAttribute 有办法查看哪些其他过滤器已执行和正在等待执行,但没有这样的运气。

我怎样才能做到这一点?由于属性似乎没有任何意识,也许是 HttpModule?自定义 ControllerActionInvoker

最佳答案

我昨晚设法让它工作了。我的解决方案如下。该属性非常标准,我已经修剪了实际的授权部分。有趣的事情发生在 HasAssignedAccessActionInvoker 中。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class RequiresAssignedAccess : AuthorizeAttribute
{
    public int AccessType { get; private set; }
    public int IdType { get; private set; }
    public int IdValue { get; private set; }
    public int Level { get; private set; }

    public RequiresAssignedAccess(int accessType, int idType, int idValue, int level)
    {
        ...
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (!base.AuthorizeCore(httpContext))
            return false;

        bool retval = ...

        return retval;
    }
}

HasAssignedAccessActionActionInvoker 继承自标准操作调用程序,但我覆盖了 InvokeAuthorizationFilters 方法以添加我们需要的授权逻辑。标准调用程序只是循环遍历授权过滤器,如果其中任何一个返回结果,它就会中断循环。

public class HasAssignedAcccessActionInvoker : ControllerActionInvoker
{
    protected override AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList<IAuthorizationFilter> filters, ActionDescriptor actionDescriptor)
    {
        AuthorizationContext authCtx = new AuthorizationContext(controllerContext, actionDescriptor);

        /*
         * If any of the filters are RequiresAssignedAccess, default this to false.  One of them must authorize the user.
         */
        bool hasAccess = !filters.Any(f => f is RequiresAssignedAccess);

        foreach (IAuthorizationFilter current in filters)
        {
            /*
             * This sets authorizationContext.Result, usually to an instance of HttpUnauthorizedResult
             */
            current.OnAuthorization(authCtx);

            if (current is RequiresAssignedAccess)
            {
                if (authCtx.Result == null)
                {
                    hasAccess = true;
                }
                else if (authCtx.Result is HttpUnauthorizedResult)
                {
                    authCtx.Result = null;
                }

                continue;
            }

            if (authCtx.Result != null)
                break;
        }

        if (!hasAccess && authCtx.Result == null)
            authCtx.Result = new HttpUnauthorizedResult();

        return authCtx;
    }
}

我必须使用 ILSpy 查看 MVC 的内部结构才能弄清楚这一点。作为引用,这是该方法的重写版本:

protected virtual AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList<IAuthorizationFilter> filters, ActionDescriptor actionDescriptor)
{
    AuthorizationContext authorizationContext = new AuthorizationContext(controllerContext, actionDescriptor);
    foreach (IAuthorizationFilter current in filters)
    {
        current.OnAuthorization(authorizationContext);
        if (authorizationContext.Result != null)
        {
            break;
        }
    }
    return authorizationContext;
}

最后,为了连接起来并使一切成为可能,我们的 Controller 继承自 BaseController,它现在返回新的调用程序。

public class BaseController : Controller
{
    protected override IActionInvoker CreateActionInvoker()
    {
        return new HasAssignedAcccessActionInvoker();
    }
}

关于c# - 相互了解的多个授权属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19778218/

相关文章:

jquery - 为移动用户界面提供响应式 asp.net web 网格的方法(使用 block 显示与隐藏某些列)

asp.net-mvc - 如何使用客户端模型将新行绑定(bind)到 ASP.NET MVC 4 WebGrid 并在客户端启用 WebGrid 的验证(数据注释)

c# - EntityFramework 在转换为基类型时抛出绑定(bind)异常

asp.net-mvc-4 - MVC 4 捆绑 URL 而不是文件

c# - 调用对象实际类型的公共(public)方法

c# - MVVM viewmodel使用async时如何设置datacontext

C#.NET : How to choose which Network adapter to connect my Application at runtime

c# - 何时检查,何时不检查 ModelState.IsValid

c# - 日期时间类型转换器

asp.net - 从 Controller 的 HTTPGET 方法将动态变量传递给自定义操作过滤器