是知道对方的多个授权属性 [英] Multiple authorization attributes that are aware of each other

查看:140
本文介绍了是知道对方的多个授权属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的场景。我想装饰与自定义授权属性我控制器/行动。如果的任何属性的有效授权应予以批准。例如,

I have a very simple scenario. I want to decorate my controllers/actions with a custom authorization attribute. Authorization should be granted if any of the attributes is valid. For example,

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

我不能参数组合成一个单一的授权属性。上面的例子是一个简单的例子,只有

I cannot combine the parameters into a single authorization attribute. The above example is a simplified example, only.

如果任一属性授权用户,我希望用户进行授权。我以为, ActionFilterAttribute AuthorizeAttribute 将不得不看到已经执行了哪些其他过滤器的手段,正在等待被执行,但没有这样的运气。

If either attribute authorizes the user, I want the user to be authorized. I assumed that ActionFilterAttribute or AuthorizeAttribute would have the means to see what other filters have been executed and are waiting to be executed, but no such luck.

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

How can I accomplish this? Since the attributes don't seem to have any awareness, maybe an HttpModule? A custom ControllerActionInvoker?

推荐答案

我设法得到这个昨晚工作。我的解决方案如下。该属性是pretty标准,我已经修剪实际的授权部分。有趣的事情发生在 HasAssignedAcccessActionInvoker

I managed to get this to work last night. My solution is below. The attribute is pretty standard and I've trimmed the actual authorization parts. The interesting stuff happens in HasAssignedAcccessActionInvoker.

[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;
    }
}

HasAssignedAcccessActionInvoker 从标准动作调用继承,但我推翻了 InvokeAuthorizationFilters 方法来添加我们需要的授权逻辑。标准调用只是旋转通过授权过滤器和其中是否返回一个结果,它打破了循环。

HasAssignedAcccessActionInvoker inherits from the standard action invoker, but I overrode the InvokeAuthorizationFilters method to add the authorization logic we need. The standard invoker just spins through the authorization filters and if any of them returns a result, it breaks the loop.

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;
    }
}

我不得不看MVC与ILSpy内部摸不着头脑。作为参考,这是该方法的重写版本:

I had to look at MVC's internals with ILSpy to figure this out. For reference, this is the overridden version of that method:

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;
}

最后,为了这样组装起来,使一切可能,我们的控制器继承 BaseController ,它现在返回新的调用。

Lastly, to wire this up and make everything possible, our controllers inherit from BaseController, which now returns the new invoker.

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

这篇关于是知道对方的多个授权属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆