防止API调用意外删除

时间:2017-10-26 15:11:42

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

我有一个删除家具或其中一个属性的Web方法:

[Authorize]
[Route("api/furniture/{furnitureId}/{property?}")]
public HttpResponseMessage Delete(string furnitureId, string property = null)
{
    try
    {
        if (property != null)
            _furnitureService.DeleteFurnitureProperty(furnitureId, property);
        else
            _furnitureService.DeleteFurniture(furnitureId);
    }
    catch (Exception ex)
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message);
    }
    return Request.CreateResponse(HttpStatusCode.Accepted);
}

当正确调用时,它按预期工作:

  • / api / furniture / id01 - 删除家具id01
  • / api / furniture / id01 / p001 - 删除家具id01上的属性p001
  • / api / furniture / id01?property = p001 - 还删除了属性p001 家具id01

但由于API使用不当,我收到了一些投诉。 例如,以下调用将删除家具:

  • / API /家具/ ID01?丙= P001

请注意,它使用了错误的 prop 参数名称,而不是 property

我知道他们有通话错误,但删除家具有一些影响,需要我自己预防(它也可以恢复,但需要消费者采取更多步骤)

所以,我的问题是:我可以轻松地检测和限制调用者何时使用除允许的参数以外的任何其他参数?这样我可以返回400错误而不是删除家具。 如果没有直接的方法,请建议更简单(如Request.Params对象正则表达式?)

1 个答案:

答案 0 :(得分:1)

编辑: 基于这个正在制作的事实,我建议创建一个ActionFilterAttribute,如下所示:

public class ValidateQueryParametersFilterAttribute : ActionFilterAttribute
{
    private IEnumerable<string> _validQueryParameters;

    public ValidateQueryParametersFilterAttribute(params string[] validQueryParameters)
    {
        if (validQueryParameters != null)
        {
            _validQueryParameters = validQueryParameters.Where(x => !string.IsNullOrWhiteSpace(x));
        }
    }

    public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        if (actionContext.Request.GetQueryNameValuePairs().Any(x => !_validQueryParameters.Contains(x.Key)))
        {
            actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "You sent me an invalid property.");
        }
        return base.OnActionExecutingAsync(actionContext, cancellationToken);
    }
}

如果您不喜欢使用params,那么您可以使用逗号分隔的字符串。很多框架使用逗号分隔的字符串而不是params。实际上,根据您的规则,您可能会在发布时收到构建错误。为简单起见,我只是做了参数。

然后将其应用于控制器,如下所示:

[ValidateQueryParametersFilter("property")]
[Route("api/furniture/{furnitureId}/{property?}")]
public async Task<HttpResponseMessage> Delete([FromUri] string furnitureId, string property = null)
{

    return Request.CreateResponse(HttpStatusCode.Accepted);
}

最佳答案是避免这种类型的路由。我会在您的API的未来版本中调整您的路线:

[Route("api/furniture/{furnitureId}/properties/{propertyId}")]

此外,我强烈建议您使用FromRouteFromQuery属性。您的控制器更改为:

[Authorize]
[Route("api/furniture/{furnitureId}/properties/{propertyId}")]
public HttpResponseMessage Delete([FromRoute] string furnitureId, [FromRoute] string property)
{
    //...
}

这使得这种关系更加清晰。此外,您可以查看https://www.nuget.org/packages/JsonPatch/以执行资源上的修补程序。

如果这不符合您的要求,请告诉我,我可以调整。

〜干杯