【问题标题】:ASP.NET MVC Controller Constructor Called Before Authentication身份验证前调用的 ASP.NET MVC 控制器构造函数
【发布时间】:2010-12-16 12:22:48
【问题描述】:

我有一个 ASP.NET MVC 应用程序,其控制器如下所示:

[Authorize]
public class MyController : Controller
{
IMyRepository myRepository;
public MyController(IMyRepository myRepository)
{
   this.myRepository = myRepository;
}

...
}

我注意到这个构造函数在验证用户之前被调用,所以如果你是第一次访问这个页面,构造函数会在你重定向到登录屏幕之前被调用。这有很多问题,登录页面加载速度较慢,该站点更容易受到 DOS 攻击,而且我对未经身份验证的、未经授权的用户能够调用“墙后”之类的代码有点紧张。

除非用户被授权,否则我可以在构造函数中检查传入请求并保释,但我使用的是 IOC (Windsor),这有点棘手,无论我是否存储,我的存储库都将被初始化实例,所以我将在每个存储库的构造函数中检查身份验证。有没有一种简单的方法可以让 .NET MVC 在调用构造函数之前对用户进行身份验证?我正在考虑将[PrincipalPermission(SecurityAction.Demand, Authenticated = true)] 添加到控制器中,但可能还有更好的方法。

编辑:

好的,不太高兴,但节目现在必须继续。我不能延迟初始化存储库,直到控制器内的某个稍后时间点。当您的控制器像我的示例中那样使用 IOC 时,您会在实例化控制器时获得存储库接口的已实例化实现。如果我可以控制正在创建的存储库,我可以轻松地调用 IsAuthenticated,而无需使用新方法。为了控制存储库初始化,您必须在每个实现中的存储库本身中实现某种延迟/延迟初始化。我不喜欢这个解决方案,因为它增加了不必要的复杂性,更重要的是控制器和存储库之间的耦合。存储库实现可以在延迟初始化没有意义的其他上下文中使用恕我直言。

【问题讨论】:

  • 假设您的 IMyRepository 实现的构造函数是轻量级的,那么我在这里看不到主要问题(即,如果设置与后备存储的实际连接是一个昂贵的过程,那么就懒惰地进行,即在第一次读/写时)。您无需再在登录页面中公开这一点,因为它也正在实例化控制器并可能访问后备存储以验证凭据。
  • @Lazarus 但是如果对我的控制器的依赖需要访问非空用户名(即用户需要在该点进行身份验证)怎么办。目前我正在为此使用Lazy<T> 实例,但我讨厌它。我认为在用户到达控制器之前对其进行身份验证太有意义了。

标签: asp.net-mvc authentication


【解决方案1】:

控制器需要在授权发生之前被实例化,因为它可以通过OnAuthorization 方法充当自己的授权过滤器。改变这种行为将涉及替换 mvc 管道的一些核心部分。您认为AuthorizedAttribute 可能无法发挥作用有什么特别的原因吗?

您可以考虑的另一个选项是在控制器方法的OnActionExecuting 中而不是在构造函数中初始化您的存储库。

【讨论】:

  • 我的控制器有相当繁重的构造函数,我不希望未经身份验证的用户能够启动代码。我知道在控制器实例化之前无法进行授权,我只想预先执行身份验证。完成后我会在这里发布我找到的所有内容。
  • 哦,如果您只是想阻止未经身份验证的用户甚至到达您的控制器,那么您可以考虑编写一个与未经身份验证的客户端不匹配的自定义路由。
  • 您可以考虑的另一个选项是在控制器方法的 OnActionExecuting 中而不是在构造函数中初始化您的存储库。
  • 对于重型构造函数,您已经查明了真正的问题。由于我们对 MVC 的工作方式无能为力,我们只能改变我们控制的东西。这是为了从你的构造函数中移除繁重的工作。
  • @marcind; OnActionExecuting 是完美的答案。如果我有足够的代表我会编辑你的答案把它放在那里。
【解决方案2】:

您可以使用 HttpModules(或 HttpHandler)在管道中更早地对请求进行身份验证。

编辑

通过OWIN 的引入,您可以配置整个请求管道中间件,并将授权放在您想要的任何阶段。与上面的想法相同,但更容易实现。

【讨论】:

    【解决方案3】:

    保罗,

    控制器的实例化是在控制器上的任何可调用操作之前的许多过程。即使攻击者试图从实例化和登录屏幕之间的这段时间间隔中受益,控制器动作也只有在动作有权这样做时才能运行,即我假设你的动作或控制器全部具有[Authorize] 属性。

    我认为您不必为此担心太多,可以高枕无忧,尽管我理解您明显的好奇心。

    【讨论】:

      【解决方案4】:

      就 DOS 攻击而言,这真的无关紧要——在第一次攻击之后(开发时经常看到),控制器实例化应该很便宜。好吧,除非您通过让构造函数执行实际工作(例如预缓存数据库查找)来对自己进行 DDOS。 . .

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        • 2011-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-29
        • 2016-10-06
        相关资源
        最近更新 更多