DDD CQRS - sorgu başına ve komut başına yetkilendirme


15

özet

CQRS / DDD'de yetkilendirme komut başına / sorgu başına uygulanmalı mı, uygulanmamalı mı?

DDD CQRS modelini az çok kesinlikle kullanarak çevrimiçi bir uygulama geliştiriyorum. Başımı gerçekten alamadığım bir problemle karşılaştım.

Oluşturduğum uygulama, insanların defter oluşturmasına izin veren ve diğer kişilerin çalışanlar gibi onları görüntülemesine / düzenlemesine / silmesine izin veren bir defter uygulamasıdır. Bir defteri kuranın yaratıcısı, oluşturduğu deftere erişim haklarını düzenleyebilmelidir. Sahipliği bile değiştirebilir. Etki alanının iki toplamı TLedger ve TUser'dir .

O yetki bir oldu belirtti vb DDD / CQRS anahtar kelime ile ilgili güvenlik, yetkilendirme, Bunların çoğu ile mesajların çok okumak Jenerik Altalan bir güvenlik uygulaması oluşturmadan sürece,.

Bu durumda, temel etki alanı kesinlikle işlemler, dengeleme ve hesaplarla ilgilenen bir muhasebe alanıdır . Ancak defterlere ince taneli erişimi yönetebilme işlevselliği de gereklidir. Bunu DDD / CQRS açısından nasıl tasarlayacağımı merak ediyorum.

Her yerde DDD eğitimlerinde komutların her yerde bulunan dilin bir parçası olduğu belirtiliyor. Anlamlılar. Bunlar "gerçek şeyi" temsil eden somut eylemlerdir.

Tüm bu komutlar ve sorgular, kullanıcıların "gerçek hayatta" gerçekleştireceği gerçek eylemler olduğundan, yetkilendirmenin uygulanması tüm bu "komutlar" ve "sorgular" ile birleştirilmeli mi? Bir kullanıcının örneğin TLedger.addTransaction () yürütme yetkisi vardır, ancak TLedger.removeTransaction () yöntemini kullanmaz. Veya bir kullanıcının "getSummaries ()" sorgusunu yürütmesine izin verilir, ancak "getTransactions ()" sorgusunu yürütmesine izin verilmez.

Erişim haklarını belirlemek için kullanıcı defteri-komutu veya kullanıcı defteri defteri sorgusu şeklinde üç boyutlu bir eşleme bulunacaktır.

Veya, ayrıştırılmış bir şekilde, "izinler" adlı bir kullanıcı için kaydedilir. Daha sonra belirli komutlar için eşlenecek izinler. Örneğin, "ManageTransactions" izni, bir kullanıcının "AddTransaction ()", "RemoveTransaction ()" vb. Yürütmesine izin verir.

  1. İzin eşleme kullanıcısı -> defter -> komut / sorgu

  2. İzin eşleme kullanıcısı -> defter -> izin -> komut / sorgu

Sorunun ilk kısmı bu. Veya kısaca, komut başına veya sorgu başına CQRS / DDD yetkisi uygulanmalı mıdır? Veya yetkilendirme komutlardan ayrılmalıdır mı?

İkincisi, izinlere dayalı yetkilendirme ile ilgili. Bir Kullanıcı, Defterleri veya yönetmesine izin verilen Defterler üzerindeki izinleri yönetebilmelidir.

  1. Yetkilendirme yönetimi komutları Defter'de gerçekleşir

Olayları / komutları / işleyicileri grantPermission (), revokePermission (), vb. Gibi Ledger toplamına eklemeyi düşündüm. Bu durumda, bu kuralların uygulanması komut işleyicilerine gerçekleşir. Ancak bu, tüm komutların söz konusu komutu yayınlayan kullanıcının kimliğini içermesini gerektirir. Sonra o kullanıcının bu komutu yürütmesine izin verilip verilmediğini TLedger'a kontrol ederim.

Örneğin :

class TLedger{ 
    function addTransactionCmdHandler(cmd){
        if (!this.permissions.exist(user, 'addTransaction')
            throw new Error('Not Authorized');
    }
}
  1. Kullanıcıdaki yetkilendirme yönetimi komutları

Bunun diğer yolu izinleri TUser'e dahil etmek olacaktır. Bir TUser'in bir dizi izinleri olurdu. Sonra, TLedger komut işleyicilerinde, kullanıcıyı alıp komutu yürütme iznine sahip olup olmadığını kontrol ederdim. Ancak bu, her TLedger komutu için TUser toplamını getirmemi gerektiriyor.

class TAddTransactionCmdHandler(cmd) {
    this.userRepository.find(cmd.userId)
    .then(function(user){
        if (!user.can(cmd)){
            throw new Error('Not authorized');
        }
        return this.ledgerRepository.find(cmd.ledgerId);
    })
    .then(function(ledger){
        ledger.addTransaction(cmd);
    })

}
  1. Hizmete sahip başka bir alan adı

Başka bir olasılık, başka bir yetkilendirme alanını tamamen modellemek olacaktır. Bu alan adı erişim hakları, yetkilendirme vb. İle ilgilenecektir. Daha sonra muhasebe alt alanı, bu yetkilendirme alanına erişmek için bir hizmet kullanır AuthorizationService.isAuthorized(user, command).

class TAddTransactionCmdHandler(cmd) {
    authService.isAuthorized(cmd)
    .then(function(authorized){
        if (!authorized) throw new Error('Not authorized');
        return this.ledgerRepository.find(cmd.ledgerId)
    })
    .then(function(){
        ledger.addTransaction(cmd);
    })

}

Hangi karar en "DDD / CQRS" yoludur?


1
Harika bir soru - Benzer sorunları çözmeye çalışıyorum ve literatürün hiçbiri doğrudan ele almıyor gibi görünüyor. Sorunuzun ikinci yarısında biraz kafam karışmıştı. İzinlerin yönetimini nereye koyacağınızı merak ediyor gibisiniz (izinleri ekleyerek veya kaldırarak), ancak gösterilen örnekler bir işlem eklemek içindir, bu yüzden ikinci yarı "izinleri nasıl sorgulamalıyım" diye soruyor gibi görünüyor. Lütfen bu kısmı aydınlatabilir misiniz?
emragins

Her işlemin yürütme politikası olabilir. Her kullanıcı bir veya daha fazla gruba ait olmalıdır, her grubun hangi işlemlere izin verildiğini belirten bir erişim profili olacaktır. Çalışma zamanında, bir işlemi gerçekleştirmeden önce, ilke, yürütme kullanıcısı için birleştirilmiş profillere karşı denetlenir. Tabii ki, bunu söylemek yapmaktan daha kolay.
NoChance

Yanıtlar:


5

İlk soru için benzer bir şeyle uğraşıyorum. Giderek daha fazla üç aşamalı bir yetkilendirme planına yöneliyorum:

1) komut / sorgu seviyesinde Yetkilendirme "Bu kullanıcının gelmez hiç bu komutu çalıştırmak için izin var mı?" Bir MVC uygulamasında bu muhtemelen denetleyici düzeyinde ele alınabilir, ancak geçerli kullanıcı ve yürütme komutuna dayalı izinler deposunu sorgulayacak genel bir ön işleyici seçiyorum.

2) "Bu kullanıcı" hiç * bu varlığa erişim izni var mı? "Uygulama yetkisi Benim durumumda bu muhtemelen sadece depodaki filtreler aracılığıyla örtük bir kontrol olacak - benim alanımda bu temelde Organizasyon Kimliği biraz daha ayrıntılı bir Kiracı Kimliği.

3) Varlıklarınızın geçici özelliklerine (Durum gibi) dayanan yetkilendirme, alan adının içinde işlenir. (Örn. "Sadece belirli kişiler kapalı bir defteri değiştirebilir.") Bunu alanın içine koymayı tercih ediyorum çünkü çok fazla alan ve iş mantığına dayanıyor ve bunu başka yerlerde göstermekten gerçekten rahat değilim.

Başkalarının bu fikre verdiği yanıtları duymak isterim - isterseniz parçalara ayırın (eğer isterseniz bazı alternatifler sağlayın :))


Farklı yetkilendirme katmanları hakkında geçerli bazı puanlarınız olduğunu düşünüyorum. Üzerinde çalıştığım bir sistemin farklı kullanıcı türleri vardı - kayıtlı kullanıcılar ve personel. Komut / sorgu işleyici izinleri, kullanıcı türünde temel bir denetim gerçekleştirdi. Personel olsaydı, her zaman geçti. Kayıtlı bir kullanıcıysa, yalnızca belirli koşulların yerine getirilmesi durumunda izin verilir (örn. Birleştirilmiş izinler).
magnus

0

Yetkilendirmeyi BC Yetkilendirmenizin bir parçası olarak uygularım, ancak bunu Ledger sisteminize bir işlem filtresi olarak dağıtırım. Bu şekilde, birbirlerinden mantıksal olarak ayrılabilirler - Defter kodunuzun Yetkilendirme kodunu çağırması gerekmez - ancak yine de gelen her istek için yüksek performanslı işlem içi yetkilendirme elde edersiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.