我正在使用breezejs,并对如何保存数据有疑问。这是我的代码和评论
[Authorize]
/*
* I want to point out the security hole here. Any Authorized user is able to pass to this method
* a saveBundle which will be saved to the DB. This saveBundle can contain anything, for any user,
* or any table.
*
* This cannot be stopped at the client level as this method can be called from Postman, curl, or whatever.
*
* The only way I can see to subvert this attack would be to examine the saveBundle and verify
* no data is being impacted that is not owned or related directly to the calling user.
*
* Brute force could be applied here because SaveResult contains Errors and impacted Entities.
*
*/
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _efContext.SaveChanges(saveBundle);
}
为了限制访问呼叫者检索数据的能力,我首先从access_token提取user_id并限制我所有的查询以将其包含在一个子句中,从而使用户不可能检索其他用户数据。
,但这不会阻止在具有增量对象ID的蛮力循环中呼叫savechanges()从呼叫savechanges()的流氓用户。
我在这一个吗?也许我缺少一些东西。
感谢您的任何帮助。
Mike
客户端传递给SaveChanges
方法的JObject saveBundle
是不透明且难以使用的。微风ContextProvider
将其转换为实体地图,并将其传递给Beforesaveentities方法。BeforeSaveEntities
是您将在ContextProvider
子类或附加到上下文提供者的委托中实现的方法,例如:
var cp = new MyContextProvider();
cp.BeforeSaveEntitiesDelegate += MySaveValidator;
在您的BeforeSaveEntities
或委托方法中,您将检查是否可以由当前用户保存该实体。如果您找到不应该保存的实体,则可以将其从更改集中删除,也可以丢弃错误并中止保存:
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(
Dictionary<Type, List<EntityInfo>> saveMap)
{
var user = GetCurrentUser();
var entityErrors = new List<EFEntityError>();
foreach (Type type in saveMap.Keys)
{
foreach (EntityInfo entityInfo in saveMap[type])
{
if (!UserCanSave(entityInfo, user))
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden)
{ ReasonPhrase = "Not authorized to make these changes" });
}
}
}
return saveMap;
}
您将需要确定是否应允许用户保存特定实体。这可以基于用户和/或其他属性的角色,例如销售角色中的用户只能保存属于自己销售区的客户记录。