多个彼此了解的授权属性
我有一个非常简单的场景。 我想用自定义授权属性装饰我的控制器/操作。 如果任何属性有效,则应授予授权。 例如,
[MyAuth(1)] [MyAuth(2)] public class MyController : Controller { ... }
我无法将参数组合到单个授权属性中。 以上示例仅是一个简化示例。
如果任一属性授权用户,我希望用户被授权。 我假设ActionFilterAttribute
或AuthorizeAttribute
可以看到其他filter已被执行并等待执行,但没有这样的运气。
我怎么能做到这一点? 由于属性似乎没有任何意识,可能是一个HttpModule
? 自定义ControllerActionInvoker
?
昨晚我设法让这个工作。 我的解决方案如下。 该属性非常标准,我已经修剪了实际的授权部分。 有趣的东西发生在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
inheritance自标准动作调用程序,但我InvokeAuthorizationFilters
了InvokeAuthorizationFilters
方法以添加我们需要的授权逻辑。 标准调用者只是通过授权filter旋转,如果它们中的任何一个返回结果,它会打破循环。
public class HasAssignedAcccessActionInvoker : ControllerActionInvoker { protected override AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList 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的内部结构来解决这个问题。 作为参考,这是该方法的重写版本:
protected virtual AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList filters, ActionDescriptor actionDescriptor) { AuthorizationContext authorizationContext = new AuthorizationContext(controllerContext, actionDescriptor); foreach (IAuthorizationFilter current in filters) { current.OnAuthorization(authorizationContext); if (authorizationContext.Result != null) { break; } } return authorizationContext; }
最后,为了使这一切成为可能,我们的控制器inheritance自BaseController
,它现在返回新的调用者。
public class BaseController : Controller { protected override IActionInvoker CreateActionInvoker() { return new HasAssignedAcccessActionInvoker(); } }
据我所知,你不能以你想要的方式链接[Authorize]
属性,因为它们都必须传递(AND)而不是(OR)行为。 但是,将项目合并为一个不会导致您必须执行一些魔术字符串操作,无论您需要传递给它的参数数量。 您可以定义自己的Authorize
属性可用的参数集。
public class SuperCoolAuthorize : AuthorizationAttribute { public string Parameter1{get;set;} public string Parameter2{get;set;} public int Parameter3{get;set;} public string Parameter4{get;set;} public override void OnAuthorization(AuthorizationContext filterContext) { // your custom behaviour } }
在你的控制器/动作方法上
[Authorize(Parameter1 = "Foo", Parameter2 = "Bar", Parameter3 = 47, Parameter4 = string.Empty) public ActionResult MyControllerAction(){ ... }
关于自定义授权属性的其他一些注意事项的一篇很棒的post我在帮助制定这个答案时遇到了。
public class AuthUserAttribute : AuthorizeAttribute { public string[] SecurityGroups; public string Groups { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { bool valid = false; var user = UserInformation.Current; if (user.SecurityGroups.Select(x => x).Intersect(this.SecurityGroups).Any()) { valid = true; } if (user.SecurityGroups.Select(x => x).Intersect(new string[] { "IT Administrators" }).Any()) { valid = true; } return valid; } public override void OnAuthorization(AuthorizationContext filterContext) { if (!this.AuthorizeCore(filterContext.HttpContext)) { if (UserInformation.Current.SecurityGroups.Count == 0) { filterContext.Result = new RedirectResult(string.Format("/oa?ReturnUrl={0}", filterContext.HttpContext.Request.RawUrl)); } else { filterContext.Result = new RedirectResult(string.Format("/oa/user/permissions?ReturnUrl={0}", filterContext.HttpContext.Request.RawUrl)); } } else { base.OnAuthorization(filterContext); } }
}
然后我装饰着
[AuthUser(SecurityGroups = new string[] { "Data1", "Data2" })] public ActionResult ForYourEyesOnly() { }
我们会看到是否有人抓住了Bond参考。 大声笑
上述就是C#学习教程:多个彼此了解的授权属性分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1030153.html