我正在使用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并限制我的所有查询以将其包含在where子句中,这使得用户无法检索其他用户数据。
但是,这不会阻止具有有效access_token的流氓用户在具有增量对象ID的暴力循环中调用SaveChanges()。
我离开这个吗?也许我错过了什么。
感谢您的帮助。
麦克
答案 0 :(得分:2)
客户端传递给JObject saveBundle
方法的SaveChanges
是不透明的,难以使用。 Breeze ContextProvider
将其转换为实体地图并将其传递给BeforeSaveEntities方法。 BeforeSaveEntities
是您在ContextProvider
子类或您附加到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;
}
您需要确定是否允许用户保存特定实体。这可以基于用户的角色和/或一些其他属性,例如, Sales角色中的用户只能保存属于他们自己的SalesRegion的客户端记录。