防止 API 调用时意外删除
Posted
技术标签:
【中文标题】防止 API 调用时意外删除【英文标题】:Prevent accidental deletion on API call 【发布时间】:2018-04-08 01:11:47 【问题描述】:我有一个网络方法来删除家具或他的一个属性:
[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 对象正则表达式?)
【问题讨论】:
用this.Request.GetQueryNameValuePairs()
之类的东西解析查询字符串并在那里检查错误的键?在动作过滤器的帮助下完成了同样的操作:***.com/a/37789473/5311735
谢谢,我查过了。将在我的情况下工作。我希望框架已经提供了一些东西
请注意,它与提供的答案不同(我会说更好),因为不需要您对有效的查询参数进行硬编码。
【参考方案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);
如果您不喜欢使用参数,那么您可以使用逗号分隔的字符串。许多框架使用逗号分隔的字符串而不是参数。事实上,根据您的规则,您可能会在发布时收到构建错误。为简单起见,我只是做了参数。
然后像这样将它应用到控制器:
[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")]
此外,我强烈建议使用FromRoute
或FromQuery
属性。您的控制器更改为:
[Authorize]
[Route("api/furniture/furnitureId/properties/propertyId")]
public HttpResponseMessage Delete([FromRoute] string furnitureId, [FromRoute] string property)
//...
这使关系更加清晰。此外,您可以查看 https://www.nuget.org/packages/JsonPatch/ 以在资源上执行 Patch。
【讨论】:
感谢您的快速回答。我同意这种关系会很清楚。不幸的是,这已经有一段时间投入生产了,它会破坏像 /api/furniture/id01/p001 这样的调用(我继承了一些错误) 好的,我想这可能是这种情况,所以我正在为您制定更好的解决方案。 @zameb 如果这对您有用,请将其标记为已回答 它有效,@Rogala。此外,制作关系更清晰的新版本的建议将得到实施并逐渐改变。谢谢 @zameb 我将来也会关注 JsonPatch。非常漂亮的 NuGet 包。最后,我强烈建议创建一个全局异常处理程序。此外,我会避免发回 ex.Message。这可能是一个安全风险,因为消息可能包含专有或敏感(连接字符串)信息。如果您愿意,您还可以扩展我的解决方案,使其更像是一个全局过滤器。以上是关于防止 API 调用时意外删除的主要内容,如果未能解决你的问题,请参考以下文章
Windows 2008 R2 域控制器防止意外删除现有OU的设置