【问题标题】:Is there a way to discriminate a specific System.Web.HttpException?有没有办法区分特定的 System.Web.HttpException?
【发布时间】:2021-10-07 16:37:33
【问题描述】:

我有一些“坏男孩”用户使用不存在的控制器调用我的网站。 比如www.myapp.com/.svn/,或者www.myapp.com/wp-admin/

该应用程序基本上抛出一个System.Web.HttpException,这ExceptionMessage找不到路径'...'的控制器或没有实现IController。

有没有办法以一种可靠的方式准确地捕捉到这个“子”System.Web.HttpException? (当然不是比较ExceptionMessage的字符串)。

任何指示确切异常的子 InnerException 类型和/或某些“代码”?

【问题讨论】:

  • HttpException 上没有可以帮助您的属性。您要么必须弄清楚如何在请求变为异常之前拦截请求,要么返回解析消息。
  • @LasseV.Karlsen 我该如何拦截它?例如,检查请求的控制器是否存在?
  • 我认为您需要在 web.config 文件中进行简单配置。请仔细阅读页面stackify.com/aspnet-mvc-error-handling
  • @AmirhosseinMehrvarzi 这适用于通用 http 消息(即 400、401 等)。在这种情况下,如果控制器不存在,我需要路由

标签: asp.net-mvc exception .net-4.6.1 httpexception


【解决方案1】:

您可以创建一个自定义 IControllerFactory,例如从DefaultControllerFactory派生。

当无法解析匹配的控制器时,将使用controllerType 参数的null 值调用其GetControllerInstance 方法。
此时,您领先于Exception

IController GetControllerInstance(RequestContext requestContext, Type controllerType)

在这里您决定如何处理请求,例如记录和/或处理特定控制器的请求。

下面的示例显示了如何将ErrorController 用作后备,执行其Index 操作方法。

class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            var routeData = requestContext.RouteData;
            routeData.Values["controller"] = "Error";
            routeData.Values["action"] = "Index";
            controllerType = typeof(ErrorController);
        }

        return base.GetControllerInstance(requestContext, controllerType);
    }
}

从内部安装自定义控制器工厂,例如Application_StartGlobal.asax.cs 中使用:

ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());

请注意,如果控制器确实存在,但操作不存在,这并不能保护您免受相关异常的影响。

例如给定一个没有Ufo 操作方法的HomeController,则url www.myapp.com/home/ufo 会导致Exception "A public action method 'ufo' was not found on controller '...HomeController"

处理这种情况的一个简单解决方案是在所有控制器都继承的自定义基本控制器中覆盖 HandleUnknownAction

下面的示例显示了共享的Error 视图 (Shared\Error.cshtml) 是如何执行的。

public abstract class BaseController : Controller
{
    protected override void HandleUnknownAction(string actionName)
    {
        View("Error").ExecuteResult(ControllerContext);
    }
}

【讨论】:

    【解决方案2】:

    您所说的问题似乎是routing 问题。

    您是否尝试过catch all 路由?...这是在没有其他路由与请求路径匹配时执行的路由。 catch all 路由是最后定义的,看起来像:

    // Specific routes here...
    
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    
    routes.MapRoute(
        "Catch-All",
        "{*controller}",
        new { controller = "Home", action = "Index" }
    );
    

    我用 .NET Core MVC 测试过

    
    // This is how it is configured in .NET Core MMVC
    app.UseEndpoints(endpoints =>
    {
       endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
       endpoints.MapControllerRoute(
                name: "catch-all",
                pattern: "{*controller}",
                defaults: new { controller="Home", action="Index" });
    });
    

    我认为管理异常,如以前的答案中所建议的那样,是一种很好的做法,但不能解决您面临的路由问题。

    你可能想看看这个关于 ASP.NET MVC 类似问题的讨论: ASP.NET MVC - Catch All Route And Default Route

    【讨论】:

    • 如果我请求随机路径,上面的代码不会加载 Home/Index :((例如 /wp-admin)。你是说这个吗?
    • 更新了我的答案,我正在使用 .NET Core 进行测试(没有可用的 ASP.NET MVC 4.6)并且能够捕获所有不匹配的 url。还包括一个关于同一问题的讨论链接。
    • 您可能会重定向到 404 页面,而不是路由到 /home/index
    • 已尝试,但不适用于 .NET 4.6.1。它触发受保护的 void Application_Error() 方法,仅此而已。
    【解决方案3】:

    像@Amirhossein mentioned 一样,由于您使用的是 .net 4.6 框架,因此您可以在 Global.asax 文件类似:

     protected void Application_Error(object sender, EventArgs e)
     { 
            var ex = Server.GetLastError();
    
            Debug.WriteLine(ex);
    
            var httpEx = ex as HttpException;
            var statusCode = httpEx?.GetHttpCode() ?? 500;
    
            Server.ClearError();
            ...
      }
    

    或者您可以通过 IIS(因为我假设您在 IIS 上托管您的应用程序)通过添加映射规则(这又可以在 web.config 中完成)或通过添加过滤器甚至防火墙来解决此问题规则(因为根据我的帐户,这些探测扫描不值得登录到您的应用程序中 - 我相信它们应该在另一个级别上处理)

    【讨论】:

      猜你喜欢
      • 2012-01-27
      • 1970-01-01
      • 1970-01-01
      • 2022-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      • 1970-01-01
      相关资源
      最近更新 更多