讓我們有下列實體系統:用於對實體控制訪問ASP.MVC最佳安全實踐
public class Doctor
{
public int ID { get; set; }
public int DepartmentID { get; set; }
public string Name { get; set; }
public ICollection<Recipe> Recipes { get; set; }
}
public class Patient
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Recipe> Recipes { get; set; }
}
public class Recipe
{
public int ID { get; set; }
public int DoctorID { get; set; }
public int PatientID { get; set; }
public Doctor Doctor { get; set; }
public Patient Patient { get; set; }
public ICollection<RecipeDetails> Details { get; set; }
}
public class RecipeDetails
{
public int ID { get; set; }
public Guid SomeGuid { get; set; }
public double SomeValue { get; set; }
}
我們也有要求:
- 醫生應該可以編輯自己的食譜
- 醫生應該能看到他的部門
- 醫生內醫生只食譜應該能夠提供的食譜 進行搜索
- 醫生應該能夠提供的食譜來生成報告的詳細信息
現在我實現了以下安全檢查:
public void ValidateAccess(Doctor doctor, Recipe aRecipe, EntityAction action)
{
if (action == EntityAction.Modify && doctor.ID == aRecipe.Doctor.ID)
return;
if (action == EntityAction.Read && doctor.DepartmentID == aRecipe.Doctor.DepartmentID)
return
throw new SecurityException();
}
這工作適合簡單的方法,當我有receipe實體,我可以通過在我的邏輯方法開始時調用此方法來輕鬆驗證訪問。
但現在我有問題,該解決方案將無法搜索,當我沒有確切的實體,而是對他們的一些統計上報工作。
讓我們想象,我要生成患者的名爲「aName」是有分量「someGuid」 receipes報告,我會有一些查詢與2個標準:
var res = RecipeRepository.Query(r => aName.Contains(r.Patient.Name)).SelectMany(r => r.Details).Where(d => d.SomeGuid == someGuid).Sum(d => d.SomeValue);
這個查詢是不正確的,它將顯示所有食譜的統計數據,包括應該隱藏的食譜。 爲了解決這個問題,我們應該加上我們的接入條件,我們的查詢:
currentDoctor.DepartmentID == r.Doctor.DepartmentID
所以現在我有查詢:
var res = RecipeRepository.Query(r => aName.Contains(r.Patient.Name) && currentDoctor.DepartmentID == r.Doctor.DepartmentID).SelectMany(r => r.Details).Where(d => d.SomeGuid == someGuid).Sum(d => d.SomeValue);
的問題是,我應該在系統中,這部分添加到每個查詢它對信息進行任何計算。
更新(2012年11月12日):
第一個例子是非常簡單的,並且StuartLC在他的帖子中提到的可以解決的。 但是我們的系統中有更復雜的報告。例如 - 顯示所有患者的食譜中含有某種guid的患者。 現在我們的查詢從另一個存儲庫開始,所以我們不能應用RecipeRepository中的私有或受保護的方法。 下面是示例查詢:
var res = PatientRepository.Query(p => p.Name.Contains(aName) && p.Recipes.Any(r => r.Details.Any(d => d.SomeGuid == someGuid)));
在這種情況下,我們仍然需要直接添加我們的過濾器進入查詢:
var res = PatientRepository.Query(p => p.Name.Contains(aName) && p.Recipes.Any(r => currentDoctor.DepartmentID == r.Doctor.DepartmentID && r.Details.Any(d => d.SomeGuid == someGuid)));
結束時更新。
什麼模式或做法可以適用於使該解決方案更容易,並防止複製粘貼表達每個查詢? 我會感謝您的回答和建議。
難道不應該是術士和藥水,醫生和處方,或廚師和食譜? – Tr1stan
可能是你對的域名,實體應該是處方...我會考慮它,但問題是關於訪問限制。 –
當然,我只是沒有幫助,有時經過漫長的一天後...... – Tr1stan