我有以下表格:公司1 - > *商店1 - > *产品
我使用以下路线编辑信息: 公司/ 1 /商店/ 3 /产品/ 4 /修改
如何确保不属于该公司的用户不会更改网址上的ID并更改其他公司的信息? 我已经在登录时存储了用户companyId,因此我可以在Stores Controller上执行此验证,因为我知道Store已关联了CompanyId,我只检查该companyId是否等于已记录的用户CompanyId。但是现在从产品中我只与商店有任何联系。
我的问题是,我应该创建一个在stores表上创建该产品的PropertyId或UserId属性,或者我应该在查询中使用连接并说db.Store.Find(UrlStoreId).Include(Products) .FirstOrDefault(o => o.CompanyId == loggedUserCompanyId);
我想知道应用程序中此类问题的约定。
提前致谢。
答案 0 :(得分:1)
对于MVC控制器,可以将当前会话的用户CompanyId记录在会话状态中,并与每个呼叫进行比较。如果ID因任何原因不匹配,则转储用户会话并将其踢回登录屏幕。对于Web API控制器,您应在Auth Token的声明中包含CompanyId以执行相同类型的验证。同样,如果发现不匹配,则应记录违规尝试并且令牌无效(如果支持)
至于连接,如果您在实体之间设置引用,那么您应该能够始终强制执行ID。
给出一个URL: 公司/ 1 /商店/ 3 /产品/ 4 /修改
if(loggedInUserCompanyId != urlCompanyId)
// Dump session, kick out.
var product = context.Companies
.Where(c=> c.CompanyId == urlCompanyId)
.SelectMany(c=> c.Stores.Where(s=> s.StoreId == urlStoreId)
.SelectMany(s => s.Products))
.SingleOrDefault(p => p.ProductId == urlProductId);
这将强制您的域的层次结构直到公司和商店,以确保有人不会尝试“调整”商店ID或产品ID等内容来访问其他公司的数据。如果您有API调用,例如/ Product / 4 / Edit,那么您应始终确保您的身份验证令牌中的声明包含足够的信息(CompanyId),以确保您可以验证产品ID 4的API调用是否属于正确的公司
为确保数据受限,您必须/应该采取更多措施,但这应该为您提供最小的起点。理想情况下,您需要在代码结构中尽可能深地进行授权检查,以确保不会错过这样的检查。我倾向于使用存储库模式来包装对DbContext的调用,而不是让控制器直接访问上下文。这样,即使我的存储库返回IQueryable,它们也会强制执行授权,以便搜索数据的控制器代码不必担心忘记包含“公司”检查。
其他选项包括在数据库级别强制执行授权,我认为可以在SQL Server中使用的选项可以单独对公司数据进行分区。 AFAIK这将涉及数据库服务器中每个租户的单独用户帐户。手动的一种方法是采用类似每个租户的架构或每个租户的数据库,以确保租户之间不会公开数据。