Role Dayalı REST API?


27

Farklı rollere sahip birkaç kullanıcının içerdiği kaynaklara erişebileceği bir REST API'si yapıyorum.

Kapsamı basit tutmak için “öğrenci / öğretmen / sınıf” etki alanını ele alalım:

GET /students erişmek için kaynaktır.

Kullanıcıların Öğrenci ve / veya Öğretmen gibi rolleri olabilir.

Öğrenciler yalnızca sınıflarındaki öğrencilere erişebilecekler. Öğretmenler, öğrettikleri sınıftaki öğrencilere erişebileceklerdir. Bazı kullanımlar öğrenci olabilir ve başka sınıflara da öğretebilir. Sınıflarındaki öğrencilere ve öğrettikleri sınıftaki öğrencilere erişimi olmalıdır.

İdeal olarak bunu iki işlev olarak uygulamak istiyorum - her rol için bir tane ve daha sonra bir kullanıcının birden fazla rolü varsa "birleştirme".

Sorum şu: Bunu uygulamak için hangi modeli kullanmalıyım?

haricen

  • API'mı rol başına bölmeli miyim? GET /teacher/studentsve GET /student/studentsbana doğru gelmiyor.
  • Hepsini bir kaynak olduğum gibi tut (tercih edilen)

içten

Dahili olarak nasıl uygulanmalıdır?

  • Her yöntem BÜYÜK bir anahtarla mı başlamalı / rol başına ise?
  • Rol başına bir depo uygulamalı mıyım?
  • Bunu başarmamda bana yardımcı olacak bir tasarım deseni var mı?

Yandan bir yorum olarak: ASP.NET Web API ve Entity Framework 6 kullanıyorum , ancak kavramsal uygulama için gerçekten önemli değil.


3
"Bu harika bir soru, bunun için bir çözüm bulup gelmediğini bilmek istiyorum, çünkü benzer bir şey yapmaya çalışıyorum. Olması gerektiğini düşündüğüm şey: İlk önce, gerekli tüm verileri veren bir api uygulayacağız. , sonra her müşteri doğrudan api'ye değil, o kullanıcıdan gelen rollere göre verileri filtrelemekten sorumlu olacak bir proxy'ye bağlanacaktır "
Cleiton

Yanıtlar:


11

API'yı roller etrafına değil kaynaklara göre oluşturmalısınız, örneğin:

/rest/students

Öğrencileri görmelerine izin veren rolü olan herkes için erişilebilir olmalıdır.

Dahili olarak, rol tabanlı güvenlik uyguluyorsunuz. Bunun nasıl yürüdüğünüz, uygulamanızın ayrıntılarına bağlıdır, ancak diyelim ki, bir rol masanız var, her bir kişinin bir veya daha fazla rolü var ve bu roller her kişinin erişebileceğini belirler. Öğrencilere erişim için kuralları zaten belirttiniz:

  • Öğrenciler, aldıkları derslerden öğrencilere erişebilirler.
  • öğretmenler öğrencilere öğrettikleri sınıflardan erişebilirler

Yani bir kişi aradığında:

/rest/students

Öğrencilerin erişimini sağlayan, kişinin rolünü geçen bir yöntem diyorsunuz. İşte bazı sahte kod:

roles = person.roles; //array
students = getStudents( roles );
return students;

ve bu yöntemde, her bir rol için öğrencileri ayrı çağrılarla elde edebilirsiniz, örneğin:

factory = getFactory();
classes= [];
students = [];
for( role in roles ){
    service = factory.getService( role );
    // implementation details of how you get classes for student/teacher are hidden in the service
    classes = classes.merge( service.getClasses( person ) );
    // classes[] has class.students[]
    // loop on classes and add each student to students, or send back classes with nested students? depends on use case
  }
}

Bu, yapabilecekleriniz için çok kaba bir fikirdir ve özel gereksinimlerinize uyması gerekmez, ancak size söz konusu parçaları anlamanız gerekir. Sınıfları listelenen her bir öğrenciyle birlikte iade etmek istiyorsanız, bu iyi bir yaklaşımdır. Sadece öğrencileri istiyorsan, onları her sınıftan çıkartabilir ve onları bir öğrenci topluluğuyla birleştirebilirsin.

Hayır, rol başına ayrı bir havuza sahip olmamalısınız. Tek yapmanız gereken veriyi nasıl aldığınızı ve belki de verilerle neler yapabileceğinizi belirlemektir (örneğin, Öğretmenler Öğrenci notlarına girebilir). Verinin kendisi aynı.

Kalıplara gelince, bu yaklaşım Rolü temel alan verileri alan hizmeti soyutlamak için Fabrika Kalıplarını kullanıyor. Rolüne göre ayrı hizmetlerin olması uygun olabilir veya olmayabilir. Bu yaklaşımı seviyorum, çünkü programın her aşamasında kod miktarını en aza indirir ve bir anahtardan veya bloktan daha okunaklı olmasını sağlar.


1
Yanıt için teşekkürler. Sonunda önerdiğin gibi bir şey yaptım. LINQ2SQL (C #) kullanarak sorguyu her "role" iletebilir ve kullanıcının aldığı her rol için bir yere başvurabilirim. Sonuç, kullanıcının erişebildiği her rol için "VEYA" koşulu olan bir sql ifadesi olur. Bir kullanıcıya hiçbir rol atanmamışsa, yalnızca arayan numarayı Enumarable.Empty () döndürürüm.
Casper Jensen,

0

Bir kalem ve bir kağıt bulun ve sisteminizi modellemeye başlayın.

Muhtemelen PERSON adlı bir etki alanı varlığına ihtiyacınız olduğunu göreceksiniz. Hem ÖĞRENCİLER hem de ÖĞRETMEN "bir" KİŞİ "olduğundan, PERSON adında, ad, soyadı, vb. Gibi genel özniteliklere sahip soyut bir varlık oluşturabilirsiniz. Artık ÖĞRENCİLERE uygulanmayan bir ÖĞRETMEN'in özelliklerini bulmaya çalışabilirsiniz; örneğin, bir ÖĞRETMEN, bir veya daha fazla KONU (lar) ile ilgili SINIF (ları) öğretir.

Güvenliği sağlamak, uygulamanızın işlevsel olmayan bir yönü olarak kabul edilir. Bu bir olan kesişen endişe sizin "iş mantığı" dışında ele alınmalıdır. @Robert Munn'ın işaret ettiği gibi, ROLE (ler) nin tümü bir yerde tutulmalıdır. Bazı işlevlere erişimi sınırlamak için rollerin kullanılması oldukça kaba bir şekilde tanımlanmıştır ve konsepte rol tabanlı erişim kontrolü (RBAC) adı verilmektedir.

Bir öğretmenin notlarını görmesine izin verilip verilmeyeceğini doğrulamak için etki alanı modelinizde ifade edilmelidir. Bir öğretmenin konu programlaması üzerinde bir sınıfı olduğunu söyleyin. Muhtemelen modelinizde öğrencilerin farklı dersler için derslere katıldığını açıklarsınız. Uygulama / iş mantığının devreye girdiği yer burasıdır. Test odaklı bir geliştirme kullanarak doğrulayabileceğiniz bir mantık budur.

Sen olmalıdır Başvurunuz test edilebilir ve modüler hale getirmek için kaynak ayrıldı.

Her neyse, gerçekten ne demek istediğimi göstermenin en iyi yolu kodla göstermektir :) İşte GitHub sayfası: https://github.com/thomasandersen77/role-based-rest-api

İyi şanslar :)


3
bağlantınız gitti ...
Cleiton
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.