【问题标题】:Catch an invalid HTTP request method globally全局捕获无效的 HTTP 请求方法
【发布时间】:2017-12-08 14:26:18
【问题描述】:

我想将我的 Web API 端点限制为某些 HTTP 方法,例如 GET 和 POST。我搜索了互联网,发现您可以在您的方法上方添加[HttpGet][HttpPost],如下所示:

[HttpPost]
public ActionResult Login(string userName, string password) {
    // do login stuff
    return View();
}

现在我想测试上面使用[HttpPost] 的示例是否真的有效,所以我使用邮递员向我的Web API 发送HTTP 请求。我填写 URI 并将方法设置为 GET。我得到的回复如下:

{
    "message": "The requested resource does not support http method 'POST'."
}

我能够验证添加 [HttpPost] 会阻止我使用 HTTP GET 请求。

我现在想做的是每当用户在应用程序期待 POST 时尝试发送 GET 请求时记录该事件,反之亦然。我可以为每一种方法实现一些东西,但这会花费很多时间,而且一旦实现就不容易进行更改。所以我想在全球范围内过滤它或其他东西。

例如:

class MethodRequestFilter : SomeGlobalMethodFilter
    {
        public override void Filter(SomeRequestContext requestContext)
        {
            if (usedRequestMethod.isNotValid == true)
            {
                //implementation for logging
            }
        }
    }

当然,我还没有在 .Net 的库中找到它。当用户尝试发出不受支持的方法的请求时,如何全局记录事件?

您好,

达米安。

【问题讨论】:

  • 那么,抓到请求后你想做什么呢?只是记录?
  • 我想通过向我的OWASP AppSensor REST 服务器发送警报来记录事件。
  • 然后您可以实现它来创建您的基本(自定义)控制器,该控制器将从 api 控制器继承,所有其他控制器将从基本控制器继承,一旦用户请求特定方法从您的基地调用它控制器并检查是否有任何错误..
  • 等一下,你的意思是,你不想使用[HttpGet]和[HttpPost]?
  • @Div 我只想使用 HttpGet 和 HttpPost,但每个请求都不同。在我的登录请求示例中,我只接受了 HttpPost 并尝试在其上使用 HttpGet,这当然不应该工作。每当我对请求应用 [HttpGet] 或 [HttpPost] 时,我都想记录恶意用户尝试执行的所有其他请求。

标签: c# asp.net asp.net-web-api logging httprequest


【解决方案1】:

一种方法是使用通用基础控制器,要实现你需要添加一个继承自ApiController的基础控制器

public class BaseController : ApiController
{
    public override async Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
    {            
        try
        {
            HttpResponseMessage response = await base.ExecuteAsync(controllerContext, cancellationToken);
            if (!response.IsSuccessStatusCode) // or if(response.StatusCode == HttpStatusCode.BadRequest) 
            {
                //log here 
            }
            return response;
        }
        catch(Exception ex)
        {
            return await InternalServerError(ex).ExecuteAsync(cancellationToken);
        }            
    }
}  

现在,假设您有 ValuesControllerLogin 方法并且它只支持 POST,这里您的所有其他控制器都继承自 BaseController 而不是 ApiController

public class ValuesController : BaseController
{ 
  [HttpPost]
  public void Login([FromBody]string value)
  {
  }
}   

所以,一旦你调用你的登录方法,它会首先调用 BaseController 方法,你会在那里得到响应。

希望这会有所帮助!

【讨论】:

  • 感谢您的建议,对我帮助很大:)
【解决方案2】:

感谢用户div 我能够通过使用实现日志记录的基本控制器来解决我的问题。这些是我必须采取的步骤:

  1. 创建一个名为BaseController的新控制器类并继承ApiController

  2. ApiController覆盖ExecuteAsync方法:

  3. 在 catch 子句中添加实现日志记录

  4. 在您希望具有日志记录功能的每个控制器类中继承新的BaseController

我在实现中使用的代码:

public class BaseController : ApiController
{
    public override async Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
    {
        try
        {
            HttpResponseMessage response = await base.ExecuteAsync(controllerContext, cancellationToken);

            return response;
        }
        catch (HttpResponseException ex)
        {               
            if (ex.Response.StatusCode == HttpStatusCode.MethodNotAllowed)
            {
                //Logging implementation
            }
            return Request.CreateErrorResponse(ex.Response.StatusCode, ex.Message);
        }   
    }            
}

如果有什么方法可以让我的代码变得更好,请告诉我:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多