我有一个网络方法来删除家具或他的一个属性:
[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/furniture/id01?prop=p001
请注意,它使用了错误的 prop 参数名称,而不是 property
我知道他们有调用错误,但是删除家具有一些影响,需要我这边预防(它也可以恢复,但需要消费者更多的步骤)
所以,我的问题是:当调用者使用允许的参数以外的任何其他参数时,我能否轻松检测和限制?这样我就可以返回 400 错误而不是删除家具。 如果没有直接的方法,请推荐更简单的方法(比如Request.Params object regex?)
最佳答案
编辑: 基于这是在生产中的事实,我建议创建如下所示的 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);
}
}
如果您不喜欢使用参数,则可以使用逗号分隔的字符串。许多框架使用逗号分隔的字符串而不是参数。事实上,根据您的规则,您可能会在发布时收到构建错误。为简单起见,我只做了参数。
然后像这样将它应用到 Controller :
[ValidateQueryParametersFilter("property")]
[Route("api/furniture/{furnitureId}/{property?}")]
public async Task<HttpResponseMessage> Delete([FromUri] string furnitureId, string property = null)
{
return Request.CreateResponse(HttpStatusCode.Accepted);
}
最佳答案是避免这种类型的路由。我会在您的 API 的 future 版本中将您的路由调整为以下内容:
[Route("api/furniture/{furnitureId}/properties/{propertyId}")]
此外,我强烈建议使用 FromRoute
或 FromQuery
属性。您的 Controller 更改为:
[Authorize]
[Route("api/furniture/{furnitureId}/properties/{propertyId}")]
public HttpResponseMessage Delete([FromRoute] string furnitureId, [FromRoute] string property)
{
//...
}
这使得关系更加清晰。另外,你可以看看 https://www.nuget.org/packages/JsonPatch/用于在资源上执行补丁。
关于c# - 防止 API 调用中的意外删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46957941/