0

我一直在使用基于授权属性的 MvcSiteMapProvider,直到我们引入了一个从AuthorizeAttribute. 主要区别在于它的构造函数签名:

public MyAuthorizeAttribute(param RoleCode[] roles) {
    Roles = string.join(",", roles.Select(r => r.ToString());
}

并且... MvcSiteMapProvider 显示了意外的结果:只有标记为的操作MyAuthorizeAttribute变得不可见。我已经通过禁用此构造函数来检查这一点——在向构造函数添加参数之前,一切都照常进行。此外 - 它不是params特定的 - 任何参数(事件 int)都会导致这种行为。

正如我从 MvcSiteMapProvider 来源中了解到的那样,它会发出一些代码来模拟授权属性 - 但看起来不可能保存由外部代码生成的程序集。我知道有一种解决方法 - 使用某种可枚举的属性,但是你有什么建议可以让它与构造函数参数一起工作吗?你知道为什么 MvcSiteMapProvider 会这样吗?

4

1 回答 1

0

所以,在花了一些时间调试之后,我意识到了答案:动态代理

问题是在 MVC 框架内的请求执行期间,没有简单的方法可以找出派生自的类如何AuthorizeAttribute执行其工作。在访问检查失败的情况下,有些可能会抛出异常,有些 - 返回 401 状态代码,有些会立即重定向到登录页面,等等。

但是 MvcSiteMapProvides 做到了!它使用以下解决方法:

  • 如果类是AuthorizeAttribute
    • 创建一个InternalAuthorize相当简单的类实例。
    • 复制那里的所有属性并
    • 调用AuthorizeCore返回布尔值的方法。
  • 别的
    • 生成从某种属性派生的代理类,
    • create instance, /// << 这里我们得到一个异常
    • 复制那里的所有属性并
    • 调用AuthorizeCore返回布尔值的方法。

很明显,制作代理并不是一件容易的事,它知道您的构造函数参数。当然,默认构造函数缺失的异常会被抛出,但它会被空的 catch 子句消耗。这真的很可悲——至少一个调试跟踪可以为我节省几个小时。

所以最后的答案是:

  • 显然你应该使用无参数属性构造函数(为什么哦,为什么在任何地方都没有提到?)
  • 制作自定义 acl 提供程序:实现IAclModule接口并在其中释放您对自己的授权属性的了解。
于 2012-10-20T12:57:44.907 回答