5

假設我有一個複雜的系統,那裏有大量的人。簡單的想法是員工/經理的關係,許多員工向一位經理報告。現在,除了經理之外,還有能夠代表經理操作管理人員的支持人員。CQRS應用橫切關注,如安全

在CQRS系統中,如何爲「編輯員工」的假設行爲建立消息模型,其中行動的調用者是輔助人員。如果員工根據經理安全關係對他們的領域中的員工採取行動,該行動才能成功。

驗證其安全性將涉及查詢數據庫以驗證被修改的人是否確實在該經理的員工鏈內。

此查詢會在何處發生?在發起「編輯員工」消息之前?

如果在發送消息之前預先驗證數據,則在最終一致的系統中,假設在處理「編輯員工」消息之前發生了一個單獨的操作,該操作已經取消了用戶的權限以完成「編輯員工「操作。如果命令處理程序未驗證該消息的安全性問題,則即使用戶不再有權執行該消息,該消息仍然會成功。

這似乎意味着雙面驗證,類似於UI驗證&服務器端驗證將是最佳的行動方案。然而,完成驗證的方法好像違反了CQRS的關鍵原則。

使用CQRS時,在處理這些和其他類似的橫切問題時,哪種方法最好?

+1

IMO沒有普遍的答案......我會一直在命令處理器端驗證*至少*和**可選**「前期」(可能在接受消息進入隊列的部分) – Yahia

+0

我還認爲區分真正的橫切關注點,如認證,簡單授權(該用戶是否允許執行此類操作)很重要,從業務規則管理是否允許特定實體的某些操作。 –

回答

3

我可能完全跳過CQRS的這個域,並讓Web層直接與數據庫層(無消息傳遞)對話。簡單的樂觀併發應該處理少數會發生的衝突。

+0

你能解釋一下你的思考過程嗎?爲什麼你的第一個陳述? –

+1

因爲這是最簡單的解決方案,所以可能可以工作:) –

+0

這絕對是真的,但是如果最簡單的總是最好的行爲方式,那麼根本就不會存在CQRS模式? –

5

首先,我同意@ Yahia的評論,說沒有一個普遍的答案。這就是說,這是我的方法。

首先,我可能會使用雙重驗證 - 一次在我的控制器中請求第一次收到時,然後在我的域中,因爲它正在處理命令。有些人可能不同意這一點,但我寧願阻止發佈一個命令,並立即讓用戶知道他們沒有被授權執行某些操作,而不是通過命令通過,並依靠最終一致性來處理某些錯誤通知以提醒用戶在他們無法執行操作之後。

所以,在僞代碼方面,這裏是我的方式來編輯員工:

控制器

[HttpPost] 
ActionResult Edit(Employee emp){ 

    //get employee org information from _employeeRepository 
    //validate if _loggedInUserID is able to edit emp.ID 

    if(isValid) { 
    //construct command 
    _commandService.EnqueueCommand(new EditEmployee(emp.ID, emp.Name, emp.Salary)); 
    } else { 
    return View("PermissionError"); 
    } 

    return Redirect("EmployeeProperties"); 
} 

所以在這裏我的命令服務拿起命令,並將其路由到適當的AR在我的域中,這將是Employee。

員工域

protected void EditEmployee(userID, employeeID, employeeName, salary){ 
    //get employee org information from _employeeRepository 
    //validate if userID is able to edit employeeID 

    if(isValid) { 
    //apply event 
    ApplyEvent(new EmployeeEdited(userID, employeeID, employeeName, salary)); 
    } 
} 

所以我會採用同樣的安全檢查中我的兩個控制器和我的域名。我想這可能是封裝的方法(很可能是封裝的標準類,我會傳遞到存儲庫)。

所以我希望這可以幫助我如何處理這種情況。讓我知道是否有問題,我會在我的答案中詳細說明。

我希望這會有所幫助。祝你好運!

+0

你爲什麼要在兩個層面上應用它?域層不是所有應該通過的點,因此應該在那裏處理諸如安全和驗證等問題? – Juri