我有一个非常简单的场景。我想用自定义授权属性装饰我的 Controller /操作。如果任何 属性有效,则应授予授权。例如,
[MyAuth(1)]
[MyAuth(2)]
public class MyController : Controller
{
...
}
我无法将这些参数组合成一个授权属性。上面的例子只是一个简化的例子。
如果任一属性授权用户,我希望用户获得授权。我假设 ActionFilterAttribute
或 AuthorizeAttribute
有办法查看哪些其他过滤器已执行和正在等待执行,但没有这样的运气。
我怎样才能做到这一点?由于属性似乎没有任何意识,也许是 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/