在 MVC 网站中使用来自 HttpModule 的重定向,“正确”的方式

Posted

技术标签:

【中文标题】在 MVC 网站中使用来自 HttpModule 的重定向,“正确”的方式【英文标题】:Using redirect from an HttpModule in an MVC web site, the "right" way 【发布时间】:2013-04-13 11:14:24 【问题描述】:

在过去:

我们使用了 Response.Redirect,它设置 302 响应标头并引发 ThreadAbortException 以防止在重定向后发生任何其他事情。

现在,使用 MVC:

我们返回一个 RedirectResult,它避免了 ThreadAbortException 的性能问题,并且还允许管道的其余部分在将结果实际发送回浏览器之前检查结果。这是对重定向的另一种思考方式——现在,重定向不再是停止执行,而是更像是从函数返回。

我的问题与混合和匹配这些模式有关。

这是要求。我们有一个 MVC 站点,站点包含一个负责身份验证的 HttpModule。如果身份验证出现任何问题,它会丢弃 cookie 并重定向到 外部 网页。因此 HttpModule 决定是发送重定向标头还是将控制权传递给 MVC 站点。如果它发送重定向标头,它必须停止执行——如果身份验证失败,我们不希望以任何方式、形状或形式访问该站点。

这样做的“正确”方法是什么? HttpModule 应该像我们一直做的那样简单地使用 Response.Redirect 吗?或者是否有一些更符合 MVC 模式的巧妙方法来实现这一点? HttpModule 有没有办法告诉管道停止处理?

或者我应该使用一些完全不同的模式,不使用 HttpModule 的东西?也许是 MVC 过滤器?问题是,模块和站点本身之间的模块化/关注点分离非常重要。有人有什么建议吗?

【问题讨论】:

【参考方案1】:

我想我会把答案放在这里,以防其他人在类似的问题域中遇到问题。

答案其实很简单。

HttpContext.ApplicationInstance.CompleteRequest()

上述调用不再引发 ThreadAbortException(在 .NET 2.0 中已更改),因此您可以安全地使用它来告诉管道停止执行。当 HttpModule 退出时,网站本身被绕过,控制直接转到 EndRequest——这正是我所需要的。这在 .NET 1.1 中是不可能的,但我认为没有很多 1.1 MVC 项目;)

【讨论】:

【参考方案2】:

由于您提到这是用于身份验证,您应该使用Authorize Attribute。您可以在 Class 级别或 Action 级别使用它。

[Authorize]
public class HomeController : Controller

    // All actions will require authorization


public class ImageController : Controller

    public ActionResult PublicImage()
    
    

    [Authorize]
    public ActionResult ImageRequiringAuth()
    
    

对于您的用例,您可能需要从 AuthorizationAttribute 继承,如 answer 中所述。

【讨论】:

感谢约翰的回复。我确实看过这种方法。以下是我决定反对它的两个原因: 1. 从事身份验证的团队与从事 UI 工作的团队是分开的。归因方法需要修改站点代码本身。我希望有一种更加组件化的方法,我可以将一个 DLL 放到 bin 文件夹中,添加一些配置,然后就可以完成了。 2. 我们正在开发的模块拦截所有请求,而不仅仅是针对网站中定义的操作的请求(例如,未作为网站操作实现的登录和注销处理程序)。

以上是关于在 MVC 网站中使用来自 HttpModule 的重定向,“正确”的方式的主要内容,如果未能解决你的问题,请参考以下文章

HTTP请求处理流程 MVC核心(MVC就是扩展了一个HttpModule)

部署网站出现System.ServiceModel.Activation.HttpModule错误

asp.net预定义的HttpModule

Response.Redirect 在自定义 HttpModule 中使用 POST 方法

HttpHandler(处理程序) 和 HttpModule(托管模块)

MVC 网站未收到来自客户端的字符串