根据URL确定端点的HTTP谓词

时间:2016-11-28 22:38:30

标签: c# rest asp.net-web-api httpverbs

对于我过去曾经做过的项目,我们将一个URL存储在应用程序数据库的一个字段中,这样当用户必须离开时,关闭他们的系统或其他什么,他们可以恢复工作打开受影响的记录。 此URL指的是在我们公开的Web API中为相关应用程序定义的Controller方法,并提供必要的参数来打开受影响的记录。

存在一个问题,我们注意到 - 很少 - 存储的端点是指POST端点,而不是GET端点。触发此条件时,我们会收到如下异常:

The parameters dictionary contains a null entry for parameter 'MyParameter' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult SomeEndpoint(Int32, Int32)' in 'MyApplication'.  An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters

我们知道要解决问题的方法:我们想要扫描URL并确定动词。如果动词是POST,我们想要重定向到特定的URL,以防止我们的应用程序陷入这种容易出错的状态。我们希望将此重定向发生在服务器端,不仅是出于安全原因,还因为它不是客户端代码问题。

我已就此主题进行了粗略的谷歌搜索,并且没有发现任何文章谈论如何对给定网址的动词进行反向工程。

问题:在给定一些网址的情况下,有没有办法确定哪些HTTP动词在C#中被引用

如果 - 我预计会出于安全考虑的原因 - 是否有任何关于避免此类问题的技术方面的建议?在发布此问题之前,我已对受影响的应用程序进行了代码审核,并且无法轻松重现导致此问题的条件(在我们的数据库中存储POST URL),并且未发现任何应导致此问题的逻辑POST URL将保存到我们的数据库中。

2 个答案:

答案 0 :(得分:2)

任何URL都可以与任何HTTP动词一起使用,包括GET,POST,PUT,DELETE等。因此,无法推断仅给出URL的动词。

即使您可以弄清楚动词何时是POST,URL也不足以重新创建页面,因为POST需要保留在请求正文(而不是URL)中的信息。

听起来您的应用程序提供了一种服务器端的书签功能。如果目的是让用户从中断的地方继续,那么您有几个选择。

  1. 不是仅存储URL,而是存储完整的HTTP请求,包括动词和表单主体。如果任何值是特定于会话的(例如会话cookie),那么您将需要能够以某种方式替换那些新值。要非常小心,因为可能会出现无法预料的后果,例如:如果POST操作做了一些无法重复的事情。此外,存储身份验证中涉及的任何内容的POST请求(例如登录页面)是一个非常糟糕的主意。

  2. 不要将用户带回POST的目标,而是将用户带回发起POST的页面。一种方法是对所有处理POST的控制器进行编程,以验证表单变量;如果它们完全丢失,则重定向到用户应该填写的页面。

  3. 考虑让用户使用浏览器功能而不是服务器逻辑来管理自己的书签。

答案 1 :(得分:1)

因此,如果你正在使用某种行动过滤器,我们就是:

public class SomeActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        CacheCurrentStep(filterContext.HttpContext.Request);
    }

    private static void CacheCurrentStep(HttpRequestBase request)
    {
        string url = request.Url.PathAndQuery;
        // Save it, however you do that
    }
}

...有可能嗅到获取动作动词的请求!

private static void CacheCurrentStep(HttpRequestBase request)
{
    if(request.HttpMethod.ToUpper() != "GET")
        return;

    string url = request.Url.PathAndQuery;
    // Save it, however you do that
}

HttpRequest类有一个公开的HttpMethod属性,它返回HEAD,GET或POST。 HttpRequest上有一个相关的属性,RequestType,它只返回GET或POST,可以代替使用。

对于未曾使用动作过滤器的未来读者,您只需使用属性注释控制器......

[SomeAction]
public class MyApiController : ApiController
{
    // Endpoints...
}

......而且你已经确定了。