Kullanıcı izin kontrolleri ve MVC nerede ve kim tarafından yapılmalıdır?


26

Kullanıcı izin kontrolleri modelde mi yoksa kontrolörde mi yapılmalı? Ve izin kontrollerini, Kullanıcı nesnesini veya bazı UserManagement yardımcısını kim ele almalı?

Nerede olmalı?

Kontrol Ünitesinde Kontrol Etme:

class MyController {
  void performSomeAction() {
    if (user.hasRightPermissions()) {
      model.someAction();
    }
  }
  ...

Kontrolörde kontrollerin yapılması Modellerin basit işlemlerin yapılmasına yardımcı olur, böylece tüm mantıkları Kontrolörlerde tutabiliriz.

Modelde Kontrol Etme:

class MyModel {
  void someAction() {
    if (user.hasRightPermissions()) {
      ...
    }
  }
  ...

Çekleri Model'e koyarak, Modeli zorlaştırırız, ancak kullanıcıların yanlışlıkla Denetleyici'de yapmaları gerekmeyen şeyleri yapmalarına izin vermediğimizden emin olun.

Ve kim tarafından?

Bir yere yerleştikten sonra kontrolleri kim yapmalı? Kullanıcı?

Class User {
  bool hasPermissions(int permissionMask) {
    ...
  }
  ...

Ama ne elde edebileceğini bilmek gerçekten kullanıcının sorumluluğunda değil, belki bir yardımcı sınıf?

Class UserManagement {
  bool hasPermissions(User user, int permissionMask) {
    ...
  }
  ...

Biliyorum, sadece bir soru sormak yaygın bir şey, pekala, bir soru, ama bunların birlikte güzelce cevaplanabileceğini düşünüyorum.

Yanıtlar:


20

Her zamanki gibi, "bağlı"

  • izin kontrolleri, işlevsel olarak bunları koymak için uygun olan her yerde çalışır.
  • Ancak, teknik bir soru soruyorsanız, cevap 'kontrolleri gerçekleştirmek için gereken verilere sahip olan nesneye kontrolleri koymak' olabilir (muhtemelen kontrol cihazıdır).
  • fakat felsefi bir soru soruyorsanız, alternatif bir cevap öneririm: kullanıcılara gerçekleştirmelerine izin verilmeyen eylemler gösterme .

Bu nedenle, ikinci durumda, bir boolean özelliği olarak uygulanan denetleyicide izin denetimine sahip olabilir ve bu özelliği, eylemi denetleyen kullanıcı arabirimindeki düğmenin veya panelin Görünür özelliğine bağlayabilirsiniz.

Bir kullanıcı olarak gerçekleştiremediğim eylemler için düğmeleri görmek sinir bozucu; eğlenceli dışında bırakılıyor gibi hissediyorum;)


Uygulamamız kontrolleri gizlemediğimiz istisnalar dışında üçüncü senaryoyu uygular, etkisiz hale getiririz. Maalesef hepsi Winforms kodunda yapıldı, bu yüzden OP sorusuyla gerçekten alakalı değil.
Dave Nay

11
" Yapamadığım eylemlerin düğmelerini görmek sinir bozucu" -> Kendi gönderinizi yükseltmeye çalışın :)
Rowan Freeman

5
Kullanıcının gerçekleştiremediği eylemler için düğmeleri gizlemek yeterli değildir, sunucu her izin isteğini kontrol etmelidir. Üçüncü madde işareti, "alternatif bir cevap" değildir, sunucu tarafında izinlerin kontrol edilmesinin yanı sıra yapılması gereken bir şeydir.
Flimm

@Flimm, talepler bir sunucu tarafından gerçekleştirilirse kabul etti; Özel soru Controller sınıfı hakkındaydı
Steven A. Lowe 21

7

Güvenlik, çapraz bir kaygıdır, bu nedenle birden fazla katmanda uygulanması gerekir. Aşağıdaki MVC'ye bir örnektir, ancak konsept diğer mimariler ve / veya modeller için geçerlidir, sadece uygulama noktalarını tanımlamanız gerekir.

Nerede olmalı?

Görünümler , bazı kullanıcılar için izinlerine bağlı olarak görüntülenmeleri gereken UI öğeleri (widget'lar, düğmeler, menüler vb.) İçerebilir. Bu, görüş motorunun sorumluluğunda olabilir , çünkü her görüşün kendi başına ele alınmasını istemiyorsunuz. Sizin için yetkilendirme yaptığınız elemanların türüne bağlı olarak, bu sorumluluğu başka bir yere taşıyın. Örneğin, bazı öğelerin gösterilmesi gereken ve bazılarının görünmediği bir menü düşünün. Öğeler bir yerde bir liste olarak uygulanabilir ve izinlere göre bu listeyi filtreleyebilir ve ardından görüntüye iletebilir.

Kontrolörler isteklere cevap verir, bu nedenle bir kullanıcı bir eylem yürütme iznine sahip değilse, eylem başlatılmadan önce kontrol edilmesi gerekir, sorumluluğu kontrol cihazında tutmak yerine eylemi eylemciye taşır . Bu, denetleyicinizi temiz tutma avantajına sahiptir ve izinlerde bir değişiklik olması durumunda, bu değişiklikleri uygulamak için denetleyicilerinizden elemek zorunda kalmazsınız.

Kaynaklar izinlere göre görüntülenir. Bu normalde veritabanı düzeyinde yapılır , çünkü her şeyi veritabanından çekmek ve ardından izinleri uygulamak istemezsiniz.

Görebildiğiniz gibi, neye yetki vermek istediğinize bağlı olarak, bunun yapılması gereken farklı yerler vardır. Amaç mümkün olduğunca göze çarpmayan olmaktır, böylece güvenlik politikanız değiştiğinde, tercihen uygulamanızın kodunu değiştirmeden kolayca uygulayabilirsiniz. Bu, izin setinin oldukça küçük olduğu ve çok sık değişmediği küçük uygulamalar için geçerli olmayabilir. Kurumsal uygulamalarda olsa da, hikaye oldukça farklı.

Bunu kim yapmalı?

Açıkça model değil. Her katmanın, yetkilendirmeyi yapan bir uygulama noktası olması gerekir. Yukarıdaki italik metin, her seviye için olası uygulama noktasını vurgular.

XACML'ye bir göz atın . Bunu olduğu gibi uygulamak zorunda değilsiniz, ancak izleyebileceğiniz bazı yönleri size verecektir.


Bu en iyi cevap. Bazı nedenlerden dolayı, en iyisi ve diğerleri, OP'nin sorduğu gibi olmayan, denetleyici ve görünüm veya görünüm ve model arasındaki farklılıkları ele alır. Teşekkürler!
redFur

1

Aşağıdaki düzeni kullanıyorum. Çoğu kullanıcı izni kontrolünün iki genel duruma bölünebileceğini söylemek gerekir:

  • denetleyici eylemine kullanıcı erişimine göre parametreleri kontrol etmeden kullanıcı rolüne göre erişim,
  • belirli bir kullanıcı ve belirli bir model arasındaki herhangi bir mantık veya ilişkiye dayanarak kullanıcının modele erişimi.

Özellikleri kontrol etmeden denetleyici eylemine erişim genellikle MVC çerçevelerinde uygulanır. Bu hiç basit: kuralları tanımlarsınız, kullanıcılarınızın rolü vardır. Siz sadece kullanıcının kurallardaki rolünü aramak için harekete geçme izni olup olmadığını kontrol edin.

Belirli bir modele kullanıcı erişimi modelde tanımlanmalıdır. (Oyuncu temel kullanıcı sınıfıdır. Müşteri, satıcı veya konuk olabilir.)

interface ICheckAccess
{
    public function checkAccess(Actor $actor, $role);
}

class SomeModel implements ICheckAccess
{
    public function checkAccess(Actor $actor, $role)
    {
        // Your permissions logic can be as sophisticated as you want.
    }
}

Bu mantığı modele yerleştirmek biraz kar getirir. Erişim kontrolü yöntemi kalıtsal olabilir, herhangi bir ekstra sınıf oluşturmanıza gerek yoktur, genel OOP avantajlarını kullanabilirsiniz.

Daha sonra, erişim kontrolünü basitleştirmek için, hemen hemen her zaman basitlik ve iyi bir stil için uygulanmış olan bazı varsayımlar alıyoruz:

  • genellikle kontrolörler bazı model sınıflarıyla ilgilidir;
  • erişim için kontrol edilen eylemler parametre olarak tekli model kimliğini alır;
  • bu parametreye daima taban denetleyici sınıfı yönteminden eşit şekilde erişilebilir;
  • eylem, id eyleminin gerçekleştirdiği modele karşılık gelen denetleyiciye yerleştirilir.

Bu varsayımlarla, model kimliğini kullanan eylemler belirli model örneği ile ilişkilendirilebilir. Aslında, çoğu eylem yukarıda belirtilen varsayımlara uyacak şekilde kolayca dönüştürülebilir ve taşınabilir.

Ardından, bazı temel soyut denetleyici sınıfları tanımlanmalı ve miras alınmalıdır.

abstract class ModelController
{
    // Retrieve model from database using id from action parameter.
    public abstract function loadModel($id);

    // Returns rules for user role to pass to SomeModel::checkAccess()
    // Something like array('view' => 'viewer', 'delete' => 'owner', 'update' => 'owner')
    public abstract function modelRules();

    public abstract fucntion getIdParameter();

    public function filterModelAccess()
    {
        $id = $this->getIdParameter();
        if(!$this->checkModelAccess($id))
            throw new HttpException(403);
    }

    public function checkModelAccess($id)
    {
        $model = $this->loadModel($id);
        $actor = My::app()->getActor();
        $rules = $this->modelRules();
        $role = $rules[My::app()->getActionName()];
        return $model->chechAccess($actor, $role);
    }
}

Menülerinizi oluştururken bir bağlantı gösterip göstermemeye karar verirken SomeController :: checkModelAccess ($ id) yöntemini çağırabilirsiniz.


PHP için özür dilerim.
George Sovetov

1

Model ikisinde de ve Görünüm

Görünümde - UI, geçerli kullanıcı ile sınırlı UI öğelerini göstermemelidir çünkü

(örneğin, "Sil" düğmesinin uygun izinlere sahip kişilere gösterilmesi gerektiğini söyleyin)

Modelde - uygulamanızın muhtemelen bir tür API'si vardır, değil mi? API, izinleri de kontrol etmek zorundadır ve muhtemelen Modeli yeniden kullanır.

(örneğin, kullanıcı arayüzünde "Sil" düğmesine ve aynı zamanda "http: / server / API / DeleteEntry / 123" API yöntemine sahip olduğunuzu söyleyin.


Modeli neden denetleyiciden seçtiniz?
Flimm

Kontrolörde neden görünüm, model ve çoğu zaman yapıldığından emin değil.
Başkan Yardımcısı

@VP kontrolörün UI öğelerini gösterme / gizleme yetkisi yok (görünümün içine bir bool var var)
jitbit 16:18

Bilmiyorum, normalde her yerde denetleyici katmanında yapılır, bu yüzden merak ettim.
Başkan Yardımcısı

0

MVC bir sunum şeklidir. Çünkü görüş ve denetleyici yalnızca sunumla ilgili sorumluluklara sahip olmalıdır. Sunum için bir uzman modu, deneysel kullanıcı arayüzü özellikleri veya farklı tasarımlar gibi bazı izinler geçerlidir. Bunlar MVC kontrol ünitesi tarafından kullanılabilir.

Diğer birçok izin türü, uygulamanın birkaç katmanı ile ilgilidir. Örneğin, yalnızca verileri görüntüleyebilen ve bir şeyleri değiştirmeyen kullanıcılara sahip olmak istiyorsanız:

  • sunum katmanı düzenleme özelliklerini gizlemek zorundadır
  • Bir düzenleme özelliğine yine de çağrılırsa, bu tespit edilebilir / gerekir (iş katmanının uygulamaya özel kısımları, etki alanına özel kısmı değil - TrainEditor, Train değil) ve muhtemelen istisnaya neden olabilir
  • Veri erişim katmanı ayrıca yazmaları da kontrol edebilir, ancak iş katmanının hızlı bir şekilde çok fazla bilgi sahibi olmasını gerektiren daha karmaşık izin türleri için iyi bir fikir olabilir.

Bu yaklaşımda bazı kopyalar var. Ancak, sunum genellikle geçici olduğundan, uygulama katmanının amaçlandığı gibi çalışması durumunda bazı gereksiz kontroller anlamına gelse bile, uygulamanın genellikle daha istikrarlı kısmında izin kontrolü için iyi bir durum söz konusu olabilir.

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.